From bd5617aa15f14a0703974a1fe2f00aa081a307e1 Mon Sep 17 00:00:00 2001 From: Duane Nykamp Date: Tue, 22 Oct 2024 10:35:42 -0500 Subject: [PATCH] Migrate additional doenetml worker tests to vitest (#245) Converts another group of cypress tests that don't need to test the DOM to vitest. A few small bug fixes identified in the conversion are included. --- .../doenetml-worker/src/components/Answer.js | 2 +- .../doenetml-worker/src/components/AsList.js | 4 +- .../doenetml-worker/src/components/Curve.js | 4 +- .../doenetml-worker/src/components/Lists.js | 21 + .../src/components/SelectRandomNumbers.js | 1 + .../src/test/tagSpecific/answer.test.ts | 2 +- .../src/test/tagSpecific/booleaninput.test.ts | 1088 + .../src/test/tagSpecific/callAction.test.ts | 2616 +++ .../src/test/tagSpecific/collect.test.ts | 2906 +++ .../src/test/tagSpecific/copy.test.ts | 8654 +++++++ .../src/test/tagSpecific/evaluate.test.ts | 3815 ++++ .../src/test/tagSpecific/extract.test.ts | 819 + .../src/test/tagSpecific/function.test.ts | 5821 +++++ .../test/tagSpecific/functioniterates.test.ts | 482 + .../src/test/tagSpecific/graph.test.ts | 1054 + .../src/test/tagSpecific/map.test.ts | 1859 ++ .../src/test/tagSpecific/math.test.ts | 1 - .../src/test/tagSpecific/mathinput.test.ts | 712 +- .../src/test/tagSpecific/number.test.ts | 1 - .../tagSpecific/sampleprimenumbers.test.ts | 607 + .../src/test/tagSpecific/select.test.ts | 3278 +++ .../tagSpecific/selectfromsequence.test.ts | 1443 ++ .../tagSpecific/selectprimenumbers.test.ts | 976 + .../selectsamplerandomnumbers.test.ts | 1895 ++ .../src/test/tagSpecific/sequence.test.ts | 1748 ++ .../src/test/tagSpecific/shuffle.test.ts | 492 + .../src/test/tagSpecific/sort.test.ts | 734 + .../src/test/tagSpecific/substitute.test.ts | 1586 ++ .../src/test/tagSpecific/text.test.ts | 1 - .../src/test/tagSpecific/textinput.test.ts | 1577 ++ .../src/test/tagSpecific/triggerset.test.ts | 1561 ++ .../src/test/tagSpecific/updatevalue.test.ts | 2901 +++ .../doenetml-worker/src/test/utils/actions.ts | 32 + .../src/test/utils/test-core.ts | 2 +- .../e2e/tagSpecific/booleaninput.cy.js | 1030 - .../cypress/e2e/tagSpecific/callaction.cy.js | 2942 --- .../cypress/e2e/tagSpecific/collect.cy.js | 5780 ----- .../cypress/e2e/tagSpecific/copy.cy.js | 18643 +--------------- .../cypress/e2e/tagSpecific/copy2.cy.js | 7718 ------- .../cypress/e2e/tagSpecific/evaluate.cy.js | 9085 -------- .../cypress/e2e/tagSpecific/extract.cy.js | 2430 -- .../cypress/e2e/tagSpecific/function.cy.js | 11510 +--------- .../e2e/tagSpecific/functioniterates.cy.js | 1245 -- .../cypress/e2e/tagSpecific/graph.cy.js | 2376 +- .../cypress/e2e/tagSpecific/map.cy.js | 5689 +---- .../e2e/tagSpecific/mathinputgraph.cy.js | 575 - .../e2e/tagSpecific/sampleprimenumbers.cy.js | 1919 -- .../e2e/tagSpecific/samplerandomnumbers.cy.js | 3016 +-- .../cypress/e2e/tagSpecific/select.cy.js | 5649 +---- .../e2e/tagSpecific/selectfromsequence.cy.js | 3822 ---- .../e2e/tagSpecific/selectprimenumbers.cy.js | 2695 --- .../e2e/tagSpecific/selectrandomnumbers.cy.js | 3012 --- .../cypress/e2e/tagSpecific/sequence.cy.js | 2406 -- .../cypress/e2e/tagSpecific/shuffle.cy.js | 652 - .../cypress/e2e/tagSpecific/sort.cy.js | 1791 -- .../cypress/e2e/tagSpecific/substitute.cy.js | 2853 --- .../cypress/e2e/tagSpecific/textinput.cy.js | 2281 -- .../cypress/e2e/tagSpecific/triggerset.cy.js | 2056 -- .../cypress/e2e/tagSpecific/updatevalue.cy.js | 3691 --- 59 files changed, 49681 insertions(+), 103880 deletions(-) create mode 100644 packages/doenetml-worker/src/test/tagSpecific/booleaninput.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/callAction.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/collect.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/copy.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/evaluate.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/extract.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/function.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/functioniterates.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/graph.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/map.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/sampleprimenumbers.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/select.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/selectfromsequence.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/selectprimenumbers.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/selectsamplerandomnumbers.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/sequence.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/shuffle.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/sort.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/substitute.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/textinput.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/triggerset.test.ts create mode 100644 packages/doenetml-worker/src/test/tagSpecific/updatevalue.test.ts delete mode 100644 packages/test-cypress/cypress/e2e/tagSpecific/callaction.cy.js delete mode 100644 packages/test-cypress/cypress/e2e/tagSpecific/collect.cy.js delete mode 100644 packages/test-cypress/cypress/e2e/tagSpecific/copy2.cy.js delete mode 100644 packages/test-cypress/cypress/e2e/tagSpecific/evaluate.cy.js delete mode 100644 packages/test-cypress/cypress/e2e/tagSpecific/extract.cy.js delete mode 100644 packages/test-cypress/cypress/e2e/tagSpecific/functioniterates.cy.js delete mode 100644 packages/test-cypress/cypress/e2e/tagSpecific/mathinputgraph.cy.js delete mode 100644 packages/test-cypress/cypress/e2e/tagSpecific/selectprimenumbers.cy.js delete mode 100644 packages/test-cypress/cypress/e2e/tagSpecific/selectrandomnumbers.cy.js delete mode 100644 packages/test-cypress/cypress/e2e/tagSpecific/sequence.cy.js delete mode 100644 packages/test-cypress/cypress/e2e/tagSpecific/shuffle.cy.js delete mode 100644 packages/test-cypress/cypress/e2e/tagSpecific/sort.cy.js delete mode 100644 packages/test-cypress/cypress/e2e/tagSpecific/substitute.cy.js delete mode 100644 packages/test-cypress/cypress/e2e/tagSpecific/triggerset.cy.js diff --git a/packages/doenetml-worker/src/components/Answer.js b/packages/doenetml-worker/src/components/Answer.js index 91b82a4d2..fef19f330 100644 --- a/packages/doenetml-worker/src/components/Answer.js +++ b/packages/doenetml-worker/src/components/Answer.js @@ -1732,7 +1732,7 @@ export default class Answer extends InlineComponent { ) { warnings.push({ message: - "An award for this answer is based on the answer's own submitted response, which will lead to unexpected behavior.", + "An award for this answer is based on the answer tag's own submitted response, which will lead to unexpected behavior.", level: 1, }); } diff --git a/packages/doenetml-worker/src/components/AsList.js b/packages/doenetml-worker/src/components/AsList.js index 75b0917be..2e965ed60 100644 --- a/packages/doenetml-worker/src/components/AsList.js +++ b/packages/doenetml-worker/src/components/AsList.js @@ -31,7 +31,7 @@ export default class AsList extends InlineComponent { inlineChildren: { dependencyType: "child", childGroups: ["inline"], - variableNames: ["text"], + variableNames: ["text", "hidden"], variablesOptional: true, }, }), @@ -39,7 +39,7 @@ export default class AsList extends InlineComponent { let textpieces = dependencyValues.inlineChildren.map(textFromComponent); - let text = textpieces.join(", "); + let text = textpieces.filter((x) => x).join(", "); return { setValue: { text } }; }, diff --git a/packages/doenetml-worker/src/components/Curve.js b/packages/doenetml-worker/src/components/Curve.js index e5e378d06..baed8f99e 100644 --- a/packages/doenetml-worker/src/components/Curve.js +++ b/packages/doenetml-worker/src/components/Curve.js @@ -4149,7 +4149,7 @@ function getNearestPointFunctionCurve({ dependencyValues, numerics }) { return result; } - // if we don't have finite values for both componentts + // if we don't have finite values for both components // there's nothing more we can do if (!(Number.isFinite(x1) && Number.isFinite(x2))) { return {}; @@ -4183,7 +4183,7 @@ function getNearestPointFunctionCurve({ dependencyValues, numerics }) { if (parMin !== -Infinity) { minT = parMin; } - if (parMax !== -Infinity) { + if (parMax !== Infinity) { maxT = parMax; } diff --git a/packages/doenetml-worker/src/components/Lists.js b/packages/doenetml-worker/src/components/Lists.js index 2d30b20da..88bed7589 100644 --- a/packages/doenetml-worker/src/components/Lists.js +++ b/packages/doenetml-worker/src/components/Lists.js @@ -1,5 +1,6 @@ import BlockComponent from "./abstract/BlockComponent"; import BaseComponent from "./abstract/BaseComponent"; +import { textFromChildren } from "../utils/text"; export class Ol extends BlockComponent { constructor(args) { @@ -172,6 +173,26 @@ export class Li extends BaseComponent { definition: () => ({ setValue: { item: true } }), }; + stateVariableDefinitions.text = { + public: true, + shadowingInstructions: { + createComponentOfType: "text", + }, + returnDependencies: () => ({ + children: { + dependencyType: "child", + childGroups: ["anything"], + variableNames: ["text", "hidden"], + variablesOptional: true, + }, + }), + definition: function ({ dependencyValues }) { + let text = textFromChildren(dependencyValues.children); + + return { setValue: { text } }; + }, + }; + return stateVariableDefinitions; } diff --git a/packages/doenetml-worker/src/components/SelectRandomNumbers.js b/packages/doenetml-worker/src/components/SelectRandomNumbers.js index a00784d0a..25af1b7d3 100644 --- a/packages/doenetml-worker/src/components/SelectRandomNumbers.js +++ b/packages/doenetml-worker/src/components/SelectRandomNumbers.js @@ -15,6 +15,7 @@ export default class SelectRandomNumbers extends SampleRandomNumbers { let attributes = super.createAttributesObject(); delete attributes.numSamples; + delete attributes.variantDeterminesSeed; attributes.assignNamesSkip = { createPrimitiveOfType: "number", diff --git a/packages/doenetml-worker/src/test/tagSpecific/answer.test.ts b/packages/doenetml-worker/src/test/tagSpecific/answer.test.ts index 9f83627ea..e8f198841 100644 --- a/packages/doenetml-worker/src/test/tagSpecific/answer.test.ts +++ b/packages/doenetml-worker/src/test/tagSpecific/answer.test.ts @@ -1462,7 +1462,7 @@ describe("Answer tag tests", async () => { expect(errorWarnings.warnings.length).eq(1); expect(errorWarnings.warnings[0].message).contain( - "An award for this answer is based on the answer's own submitted response", + "An award for this answer is based on the answer tag's own submitted response", ); expect(errorWarnings.warnings[0].level).eq(1); expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(2); diff --git a/packages/doenetml-worker/src/test/tagSpecific/booleaninput.test.ts b/packages/doenetml-worker/src/test/tagSpecific/booleaninput.test.ts new file mode 100644 index 000000000..311bb3516 --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/booleaninput.test.ts @@ -0,0 +1,1088 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { cleanLatex } from "../utils/math"; +import { + updateBooleanInputValue, + updateMathInputValue, +} from "../utils/actions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +describe("BooleanInput tag tests", async () => { + it("single boolean input", async () => { + let core = await createTestCore({ + doenetML: ` + + + + $bi1{name="v1"} + $v1{name="v2"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi1"].stateValues.value).eq(false); + expect(stateVariables["/v1"].stateValues.value).eq(false); + expect(stateVariables["/v2"].stateValues.value).eq(false); + expect(stateVariables["/bi1"].stateValues.label).eq("hello"); + + // check the box + await updateBooleanInputValue({ + boolean: true, + componentName: "/bi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi1"].stateValues.value).eq(true); + expect(stateVariables["/v1"].stateValues.value).eq(true); + expect(stateVariables["/v2"].stateValues.value).eq(true); + + // uncheck the box + await updateBooleanInputValue({ + boolean: false, + componentName: "/bi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi1"].stateValues.value).eq(false); + expect(stateVariables["/v1"].stateValues.value).eq(false); + expect(stateVariables["/v2"].stateValues.value).eq(false); + }); + + it("single boolean input, starts checked", async () => { + let core = await createTestCore({ + doenetML: ` + + $bi1{name="v1"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi1"].stateValues.value).eq(true); + expect(stateVariables["/v1"].stateValues.value).eq(true); + + // uncheck the box + await updateBooleanInputValue({ + boolean: false, + componentName: "/bi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi1"].stateValues.value).eq(false); + expect(stateVariables["/v1"].stateValues.value).eq(false); + + // recheck the box + await updateBooleanInputValue({ + boolean: true, + componentName: "/bi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi1"].stateValues.value).eq(true); + expect(stateVariables["/v1"].stateValues.value).eq(true); + }); + + it("copied boolean input", async () => { + let core = await createTestCore({ + doenetML: ` +

+ +

+

+

$bi1{name="v1"}

+

+ +

+

$bi2{name="v2"}

+ `, + }); + + async function check_items(bi1: boolean, bi2: boolean) { + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi1"].stateValues.value).eq(bi1); + expect(stateVariables["/bi1a"].stateValues.value).eq(bi1); + expect(stateVariables["/v1"].stateValues.value).eq(bi1); + expect(stateVariables["/bi2"].stateValues.value).eq(bi2); + expect(stateVariables["/v2"].stateValues.value).eq(bi2); + + expect(stateVariables["/bi1"].stateValues.label).eq("green"); + expect(stateVariables["/bi1a"].stateValues.label).eq("green"); + expect(stateVariables["/bi2"].stateValues.label).eq("red"); + + expect(stateVariables["/pbi1"].stateValues.text).eq(bi1.toString()); + expect(stateVariables["/pbi1a"].stateValues.text).eq( + bi1.toString(), + ); + expect(stateVariables["/pv1"].stateValues.text).eq(bi1.toString()); + expect(stateVariables["/pbi2"].stateValues.text).eq(bi2.toString()); + expect(stateVariables["/pv2"].stateValues.text).eq(bi2.toString()); + + expect(stateVariables["/bi1"].componentType).eq("booleanInput"); + expect(stateVariables["/bi1a"].componentType).eq("booleanInput"); + expect(stateVariables["/bi2"].componentType).eq("booleanInput"); + expect(stateVariables["/v1"].componentType).eq("boolean"); + expect(stateVariables["/v2"].componentType).eq("boolean"); + } + + let bi1 = true, + bi2 = false; + + await check_items(bi1, bi2); + + // uncheck the first input + bi1 = false; + await updateBooleanInputValue({ + boolean: bi1, + componentName: "/bi1", + core, + }); + await check_items(bi1, bi2); + + // check the second input + bi1 = true; + await updateBooleanInputValue({ + boolean: bi1, + componentName: "/bi1a", + core, + }); + await check_items(bi1, bi2); + + // click the third input + bi2 = true; + await updateBooleanInputValue({ + boolean: bi2, + componentName: "/bi2", + core, + }); + await check_items(bi1, bi2); + }); + + it("downstream from booleanInput", async () => { + let core = await createTestCore({ + doenetML: ` +

Original boolean: true

+

booleanInput based on boolean:

+

Copied boolean: $b1{name="b2"}

+

Copied boolean input value: $bi1{name="b3"}

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi1"].stateValues.value).eq(true); + expect(stateVariables["/b1"].stateValues.value).eq(true); + expect(stateVariables["/b2"].stateValues.value).eq(true); + expect(stateVariables["/b3"].stateValues.value).eq(true); + + // change value + await updateBooleanInputValue({ + boolean: false, + componentName: "/bi1", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi1"].stateValues.value).eq(false); + expect(stateVariables["/b1"].stateValues.value).eq(false); + expect(stateVariables["/b2"].stateValues.value).eq(false); + expect(stateVariables["/b3"].stateValues.value).eq(false); + }); + + it("downstream from booleanInput, prefill ignored", async () => { + let core = await createTestCore({ + doenetML: ` +

Original boolean: true

+

booleanInput based on boolean:

+

Value:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi1"].stateValues.value).eq(true); + expect(stateVariables["/b1"].stateValues.value).eq(true); + expect(stateVariables["/b2"].stateValues.value).eq(true); + + // change value + await updateBooleanInputValue({ + boolean: false, + componentName: "/bi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi1"].stateValues.value).eq(false); + expect(stateVariables["/b1"].stateValues.value).eq(false); + expect(stateVariables["/b2"].stateValues.value).eq(false); + }); + + it("downstream from booleanInput, values revert if not updatable", async () => { + let core = await createTestCore({ + doenetML: ` +

Original boolean: can't update me

+

booleanInput based on boolean:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi1"].stateValues.value).eq(false); + expect(stateVariables["/b1"].stateValues.value).eq(false); + + // attempt to change value, but it reverts + await updateBooleanInputValue({ + boolean: true, + componentName: "/bi1", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi1"].stateValues.value).eq(false); + expect(stateVariables["/b1"].stateValues.value).eq(false); + }); + + it("downstream from booleanInput via child", async () => { + let core = await createTestCore({ + doenetML: ` +

Original boolean: true

+

booleanInput based on boolean: $b1

+

Copied boolean: $b1{name="b2"}

+

Copied boolean input value: $bi1{name="b3"}

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi1"].stateValues.value).eq(true); + expect(stateVariables["/b1"].stateValues.value).eq(true); + expect(stateVariables["/b2"].stateValues.value).eq(true); + expect(stateVariables["/b3"].stateValues.value).eq(true); + + // change value + await updateBooleanInputValue({ + boolean: false, + componentName: "/bi1", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi1"].stateValues.value).eq(false); + expect(stateVariables["/b1"].stateValues.value).eq(false); + expect(stateVariables["/b2"].stateValues.value).eq(false); + expect(stateVariables["/b3"].stateValues.value).eq(false); + }); + + it("downstream from booleanInput via child, prefill ignored", async () => { + let core = await createTestCore({ + doenetML: ` +

Original boolean: true

+

booleanInput based on boolean: $b1

+

Value:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi1"].stateValues.value).eq(true); + expect(stateVariables["/b1"].stateValues.value).eq(true); + expect(stateVariables["/b2"].stateValues.value).eq(true); + + // change value + await updateBooleanInputValue({ + boolean: false, + componentName: "/bi1", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi1"].stateValues.value).eq(false); + expect(stateVariables["/b1"].stateValues.value).eq(false); + expect(stateVariables["/b2"].stateValues.value).eq(false); + }); + + it("downstream from booleanInput via child, values revert if not updatable", async () => { + let core = await createTestCore({ + doenetML: ` +

Original boolean: can't update me

+

booleanInput based on boolean: $b1

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi1"].stateValues.value).eq(false); + expect(stateVariables["/b1"].stateValues.value).eq(false); + + // attempt to change value, but it reverts + await updateBooleanInputValue({ + boolean: true, + componentName: "/bi1", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi1"].stateValues.value).eq(false); + expect(stateVariables["/b1"].stateValues.value).eq(false); + }); + + it("downstream from booleanInput via child, bindValueTo ignored", async () => { + let core = await createTestCore({ + doenetML: ` +

Original boolean: true

+

Not bound: false

+

booleanInput based on boolean: $b1

+

Copied boolean: $b1{name="b2"}

+

Copied boolean input value: $bi1{name="b3"}

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi1"].stateValues.value).eq(true); + expect(stateVariables["/b1"].stateValues.value).eq(true); + expect(stateVariables["/b2"].stateValues.value).eq(true); + expect(stateVariables["/b3"].stateValues.value).eq(true); + expect(stateVariables["/bIgnored"].stateValues.value).eq(false); + + // change value + await updateBooleanInputValue({ + boolean: false, + componentName: "/bi1", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi1"].stateValues.value).eq(false); + expect(stateVariables["/b1"].stateValues.value).eq(false); + expect(stateVariables["/b2"].stateValues.value).eq(false); + expect(stateVariables["/b3"].stateValues.value).eq(false); + expect(stateVariables["/bIgnored"].stateValues.value).eq(false); + }); + + it("chain update off booleanInput", async () => { + let core = await createTestCore({ + doenetML: ` + + 1 + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n"].stateValues.value).eq(1); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/bi", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n"].stateValues.value).eq(2); + + await updateBooleanInputValue({ + boolean: false, + componentName: "/bi", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n"].stateValues.value).eq(3); + }); + + it("boolean input with math in label", async () => { + let core = await createTestCore({ + doenetML: ` +

+ +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi"].stateValues.label).eq( + "It is \\(\\int_a^b f(x)\\,dx\\)", + ); + + // hide label + await core.requestAction({ + componentName: "/toggleLabel", + actionName: "updateValue", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi"].stateValues.label).eq(""); + + // show label again + await core.requestAction({ + componentName: "/toggleLabel", + actionName: "updateValue", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi"].stateValues.label).eq( + "It is \\(\\int_a^b f(x)\\,dx\\)", + ); + }); + + it("boolean input with labelIsName", async () => { + let core = await createTestCore({ + doenetML: ` +

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/AnInput"].stateValues.label).eq("An Input"); + }); + + it("boolean input in graph", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + +

Anchor 1 coordinates:

+

Anchor 2 coordinates:

+

Change anchor 1 coordinates:

+

Change anchor 2 coordinates:

+

Position from anchor 1: $booleanInput1.positionFromAnchor

+

Position from anchor 2: $booleanInput2.positionFromAnchor

+

Change position from anchor 1 + + upperRight + upperLeft + lowerRight + lowerLeft + left + right + top + bottom + center + +

+

Change position from anchor 2 + + upperRight + upperLeft + lowerRight + lowerLeft + left + right + top + bottom + center + +

+

Draggable 1: $draggable1

+

Draggable 2: $draggable2

+

Change draggable 1

+

Change draggable 2

+

Disabled 1: $disabled1

+

Disabled 2: $disabled2

+

Change disabled 1

+

Change disabled 2

+

Fixed 1: $fixed1

+

Fixed 2: $fixed2

+

Change fixed 1

+

Change fixed 2

+

FixLocation 1: $fixLocation1

+

FixLocation 2: $fixLocation2

+

Change fixLocation 1

+

Change fixLocation 2

+ + `, + }); + + // TODO: how to click on the checkboxes and test if they are disabled? + + let stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex( + stateVariables["/booleanInput1anchor"].stateValues.latex, + ), + ).eq("(1,3)"); + expect( + cleanLatex( + stateVariables["/booleanInput2anchor"].stateValues.latex, + ), + ).eq("(0,0)"); + + expect(stateVariables["/pPositionFromAnchor1"].stateValues.text).eq( + "Position from anchor 1: upperright", + ); + expect(stateVariables["/pPositionFromAnchor2"].stateValues.text).eq( + "Position from anchor 2: center", + ); + expect( + stateVariables["/positionFromAnchor1"].stateValues.selectedIndices, + ).eqls([1]); + expect( + stateVariables["/positionFromAnchor2"].stateValues.selectedIndices, + ).eqls([9]); + + expect(stateVariables["/pDraggable1"].stateValues.text).eq( + "Draggable 1: true", + ); + expect(stateVariables["/pDraggable2"].stateValues.text).eq( + "Draggable 2: true", + ); + expect(stateVariables["/pDisabled1"].stateValues.text).eq( + "Disabled 1: true", + ); + expect(stateVariables["/pDisabled2"].stateValues.text).eq( + "Disabled 2: false", + ); + expect(stateVariables["/pFixed1"].stateValues.text).eq( + "Fixed 1: false", + ); + expect(stateVariables["/pFixed2"].stateValues.text).eq( + "Fixed 2: false", + ); + expect(stateVariables["/pFixLocation1"].stateValues.text).eq( + "FixLocation 1: false", + ); + expect(stateVariables["/pFixLocation2"].stateValues.text).eq( + "FixLocation 2: false", + ); + + // move booleanInputs by dragging + await core.requestAction({ + actionName: "moveInput", + componentName: "/booleanInput1", + args: { x: -2, y: 3 }, + event: null, + }); + await core.requestAction({ + actionName: "moveInput", + componentName: "/booleanInput2", + args: { x: 4, y: -5 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex( + stateVariables["/booleanInput1anchor"].stateValues.latex, + ), + ).eq("(-2,3)"); + expect( + cleanLatex( + stateVariables["/booleanInput2anchor"].stateValues.latex, + ), + ).eq("(4,-5)"); + + // move booleanInputs by entering coordinates + + await updateMathInputValue({ + latex: "(6,7)", + componentName: "/anchorCoords1", + core, + }); + await updateMathInputValue({ + latex: "(8,9)", + componentName: "/anchorCoords2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex( + stateVariables["/booleanInput1anchor"].stateValues.latex, + ), + ).eq("(6,7)"); + expect( + cleanLatex( + stateVariables["/booleanInput2anchor"].stateValues.latex, + ), + ).eq("(8,9)"); + + // change position from anchor + await core.requestAction({ + actionName: "updateSelectedIndices", + componentName: "/positionFromAnchor1", + args: { selectedIndices: [4] }, + event: null, + }); + await core.requestAction({ + actionName: "updateSelectedIndices", + componentName: "/positionFromAnchor2", + args: { selectedIndices: [3] }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pPositionFromAnchor1"].stateValues.text).eq( + "Position from anchor 1: lowerleft", + ); + expect(stateVariables["/pPositionFromAnchor2"].stateValues.text).eq( + "Position from anchor 2: lowerright", + ); + + // make not draggable + await updateBooleanInputValue({ + boolean: false, + componentName: "/draggable1", + core, + }); + await updateBooleanInputValue({ + boolean: false, + componentName: "/draggable2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pDraggable1"].stateValues.text).eq( + "Draggable 1: false", + ); + expect(stateVariables["/pDraggable2"].stateValues.text).eq( + "Draggable 2: false", + ); + + // cannot move booleanInputs by dragging + await core.requestAction({ + actionName: "moveInput", + componentName: "/booleanInput1", + args: { x: -10, y: -9 }, + event: null, + }); + await core.requestAction({ + actionName: "moveInput", + componentName: "/booleanInput2", + args: { x: -8, y: -7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex( + stateVariables["/booleanInput1anchor"].stateValues.latex, + ), + ).eq("(6,7)"); + expect( + cleanLatex( + stateVariables["/booleanInput2anchor"].stateValues.latex, + ), + ).eq("(8,9)"); + + // make draggable again + await updateBooleanInputValue({ + boolean: true, + componentName: "/draggable1", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/draggable2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pDraggable1"].stateValues.text).eq( + "Draggable 1: true", + ); + expect(stateVariables["/pDraggable2"].stateValues.text).eq( + "Draggable 2: true", + ); + + await core.requestAction({ + actionName: "moveInput", + componentName: "/booleanInput1", + args: { x: -10, y: -9 }, + event: null, + }); + await core.requestAction({ + actionName: "moveInput", + componentName: "/booleanInput2", + args: { x: -8, y: -7 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex( + stateVariables["/booleanInput1anchor"].stateValues.latex, + ), + ).eq("(-10,-9)"); + expect( + cleanLatex( + stateVariables["/booleanInput2anchor"].stateValues.latex, + ), + ).eq("(-8,-7)"); + + // fix location + await updateBooleanInputValue({ + boolean: true, + componentName: "/fixLocation1", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/fixLocation2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pFixLocation1"].stateValues.text).eq( + "FixLocation 1: true", + ); + expect(stateVariables["/pFixLocation2"].stateValues.text).eq( + "FixLocation 2: true", + ); + + // can change coordinates entering coordinates only for input 1 + await updateMathInputValue({ + latex: "(3,4)", + componentName: "/anchorCoords2", + core, + }); + await updateMathInputValue({ + latex: "(1,2)", + componentName: "/anchorCoords1", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex( + stateVariables["/booleanInput1anchor"].stateValues.latex, + ), + ).eq("(1,2)"); + expect( + cleanLatex( + stateVariables["/booleanInput2anchor"].stateValues.latex, + ), + ).eq("(-8,-7)"); + + // cannot move booleanInputs by dragging + await core.requestAction({ + actionName: "moveInput", + componentName: "/booleanInput1", + args: { x: 4, y: 6 }, + event: null, + }); + await core.requestAction({ + actionName: "moveInput", + componentName: "/booleanInput2", + args: { x: 7, y: 8 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex( + stateVariables["/booleanInput1anchor"].stateValues.latex, + ), + ).eq("(1,2)"); + expect( + cleanLatex( + stateVariables["/booleanInput2anchor"].stateValues.latex, + ), + ).eq("(-8,-7)"); + + // can change position from anchor only for input 1 + await core.requestAction({ + actionName: "updateSelectedIndices", + componentName: "/positionFromAnchor2", + args: { selectedIndices: [8] }, + event: null, + }); + await core.requestAction({ + actionName: "updateSelectedIndices", + componentName: "/positionFromAnchor1", + args: { selectedIndices: [7] }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pPositionFromAnchor1"].stateValues.text).eq( + "Position from anchor 1: top", + ); + expect(stateVariables["/pPositionFromAnchor2"].stateValues.text).eq( + "Position from anchor 2: lowerright", + ); + + // can change disabled attribute + await updateBooleanInputValue({ + boolean: false, + componentName: "/disabled1", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/disabled2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pDisabled1"].stateValues.text).eq( + "Disabled 1: false", + ); + expect(stateVariables["/pDisabled2"].stateValues.text).eq( + "Disabled 2: true", + ); + + // make completely fixed + await updateBooleanInputValue({ + boolean: true, + componentName: "/fixed1", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/fixed2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pFixed1"].stateValues.text).eq("Fixed 1: true"); + expect(stateVariables["/pFixed2"].stateValues.text).eq("Fixed 2: true"); + + // can change coordinates entering coordinates only for input 1 + await updateMathInputValue({ + latex: "(7,8)", + componentName: "/anchorCoords2", + core, + }); + await updateMathInputValue({ + latex: "(5,6)", + componentName: "/anchorCoords1", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex( + stateVariables["/booleanInput1anchor"].stateValues.latex, + ), + ).eq("(5,6)"); + expect( + cleanLatex( + stateVariables["/booleanInput2anchor"].stateValues.latex, + ), + ).eq("(-8,-7)"); + + // can change position from anchor only for math 1 + await core.requestAction({ + actionName: "updateSelectedIndices", + componentName: "/positionFromAnchor2", + args: { selectedIndices: [5] }, + event: null, + }); + await core.requestAction({ + actionName: "updateSelectedIndices", + componentName: "/positionFromAnchor1", + args: { selectedIndices: [6] }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pPositionFromAnchor1"].stateValues.text).eq( + "Position from anchor 1: right", + ); + expect(stateVariables["/pPositionFromAnchor2"].stateValues.text).eq( + "Position from anchor 2: lowerright", + ); + + // can change disabled attribute only for input 1 + + await updateBooleanInputValue({ + boolean: true, + componentName: "/disabled1", + core, + }); + await updateBooleanInputValue({ + boolean: false, + componentName: "/disabled2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pDisabled1"].stateValues.text).eq( + "Disabled 1: true", + ); + expect(stateVariables["/pDisabled2"].stateValues.text).eq( + "Disabled 2: true", + ); + }); + + it("valueChanged", async () => { + let doenetML = ` +

+

+

+

$bi2

+ + `; + + async function check_items( + [bi1, bi2]: [bi1: boolean, bi2: boolean], + [bi1changed, bi2changed, bi3changed, bi4changed]: [ + bi1changed: boolean, + bi2changed: boolean, + bi3changed: boolean, + bi4changed: boolean, + ], + ) { + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/bi1"].stateValues.value).eq(bi1); + expect(stateVariables["/bi2"].stateValues.value).eq(bi2); + expect(stateVariables["/bi3"].stateValues.value).eq(bi1); + expect(stateVariables["/bi4"].stateValues.value).eq(bi2); + + expect(stateVariables["/bi1a"].stateValues.value).eq(bi1); + expect(stateVariables["/bi2a"].stateValues.value).eq(bi2); + expect(stateVariables["/bi3a"].stateValues.value).eq(bi1); + expect(stateVariables["/bi4a"].stateValues.value).eq(bi2); + + expect(stateVariables["/bi1changed"].stateValues.value).eq( + bi1changed, + ); + expect(stateVariables["/bi2changed"].stateValues.value).eq( + bi2changed, + ); + expect(stateVariables["/bi3changed"].stateValues.value).eq( + bi3changed, + ); + expect(stateVariables["/bi4changed"].stateValues.value).eq( + bi4changed, + ); + } + + let core = await createTestCore({ + doenetML, + }); + + let stateVariables = await returnAllStateVariables(core); + + let bi1 = false, + bi2 = true; + let bi1changed = false, + bi2changed = false, + bi3changed = false, + bi4changed = false; + + await check_items( + [bi1, bi2], + [bi1changed, bi2changed, bi3changed, bi4changed], + ); + + // clicking first marks only first as changed + bi1 = true; + bi1changed = true; + await updateBooleanInputValue({ + boolean: bi1, + componentName: "/bi1", + core, + }); + await check_items( + [bi1, bi2], + [bi1changed, bi2changed, bi3changed, bi4changed], + ); + + // clicking second marks only second as changed + + bi2 = false; + bi2changed = true; + await updateBooleanInputValue({ + boolean: bi2, + componentName: "/bi2", + core, + }); + await check_items( + [bi1, bi2], + [bi1changed, bi2changed, bi3changed, bi4changed], + ); + + // clicking third and fourth + + bi1 = false; + bi2 = true; + bi3changed = true; + bi4changed = true; + await updateBooleanInputValue({ + boolean: bi1, + componentName: "/bi3", + core, + }); + await updateBooleanInputValue({ + boolean: bi2, + componentName: "/bi4", + core, + }); + await check_items( + [bi1, bi2], + [bi1changed, bi2changed, bi3changed, bi4changed], + ); + + // reload + core = await createTestCore({ + doenetML, + }); + + bi1 = false; + bi2 = true; + bi1changed = false; + bi2changed = false; + bi3changed = false; + bi4changed = false; + + await check_items( + [bi1, bi2], + [bi1changed, bi2changed, bi3changed, bi4changed], + ); + + // clicking third marks first and third as changed + + bi1 = true; + bi1changed = true; + bi3changed = true; + await updateBooleanInputValue({ + boolean: bi1, + componentName: "/bi3", + core, + }); + await check_items( + [bi1, bi2], + [bi1changed, bi2changed, bi3changed, bi4changed], + ); + + // clicking fourth marks only second and fourth as changed + + bi2 = false; + bi2changed = true; + bi4changed = true; + await updateBooleanInputValue({ + boolean: bi2, + componentName: "/bi4", + core, + }); + await check_items( + [bi1, bi2], + [bi1changed, bi2changed, bi3changed, bi4changed], + ); + + // clicking first and second + bi1 = false; + bi2 = true; + + await updateBooleanInputValue({ + boolean: bi1, + componentName: "/bi1", + core, + }); + await updateBooleanInputValue({ + boolean: bi2, + componentName: "/bi2", + core, + }); + await check_items( + [bi1, bi2], + [bi1changed, bi2changed, bi3changed, bi4changed], + ); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/callAction.test.ts b/packages/doenetml-worker/src/test/tagSpecific/callAction.test.ts new file mode 100644 index 000000000..f8ae883e3 --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/callAction.test.ts @@ -0,0 +1,2616 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { cleanLatex } from "../utils/math"; +import { + updateBooleanInputValue, + updateMathInputValue, +} from "../utils/actions"; +import me from "math-expressions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +describe("callAction tag tests", async () => { + async function test_resample(core) { + let stateVariables = await returnAllStateVariables(core); + + let sum = 0; + let numbers = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers.length).eq(5); + for (let [ind, num] of numbers.entries()) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + sum += num * 10 ** ind; + } + + expect(stateVariables["/sum"].stateValues.value).eq(sum); + + await core.requestAction({ + componentName: "/rs", + actionName: "callAction", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/sum"].stateValues.value).not.eq(sum); + + let numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + + expect(numbers2.length).eq(5); + for (let num of numbers2) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + expect(numbers2).not.eqls(numbers); + } + + it("resample random numbers", async () => { + let core = await createTestCore({ + doenetML: ` +

+

+ +

+

Sum: + + + $s + +

+ `, + }); + + await test_resample(core); + }); + + it("add and delete points", async () => { + let core = await createTestCore({ + doenetML: ` +
+ The graphs + + (1,2) + + + $g{name="g2"} +
+ + $theGraphs{name="theGraphs2"} + +

points from graph:

+ + + (3,4) + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/p1"].stateValues.latex)).eq("(1,2)"); + + let g1 = stateVariables["/theGraphs/g"]; + let g2 = stateVariables["/theGraphs/g2"]; + let g3 = stateVariables["/theGraphs2/g"]; + let g4 = stateVariables["/theGraphs2/g2"]; + let gs = [g1, g2, g3, g4]; + + for (let g of gs) { + expect(g.stateValues.graphicalDescendants.length).eq(1); + } + + await core.requestAction({ + componentName: "/addPoint", + actionName: "callAction", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/p2"].stateValues.latex)).eq("(3,4)"); + + g1 = stateVariables["/theGraphs/g"]; + g2 = stateVariables["/theGraphs/g2"]; + g3 = stateVariables["/theGraphs2/g"]; + g4 = stateVariables["/theGraphs2/g2"]; + gs = [g1, g2, g3, g4]; + + for (let g of gs) { + let pointNames = g.stateValues.graphicalDescendants.map( + (x) => x.componentName, + ); + expect(pointNames.length).eq(2); + expect( + stateVariables[pointNames[0]].stateValues.xs.map((x) => x.tree), + ).eqls([1, 2]); + expect( + stateVariables[pointNames[1]].stateValues.xs.map((x) => x.tree), + ).eqls([3, 4]); + } + + await core.requestAction({ + actionName: "movePoint", + componentName: g1.stateValues.graphicalDescendants[1].componentName, + args: { x: -2, y: 5 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/p2"].stateValues.latex)).eq( + "(-2,5)", + ); + + g1 = stateVariables["/theGraphs/g"]; + g2 = stateVariables["/theGraphs/g2"]; + g3 = stateVariables["/theGraphs2/g"]; + g4 = stateVariables["/theGraphs2/g2"]; + gs = [g1, g2, g3, g4]; + + for (let g of gs) { + let pointNames = g.stateValues.graphicalDescendants.map( + (x) => x.componentName, + ); + expect( + stateVariables[pointNames[1]].stateValues.xs.map((x) => x.tree), + ).eqls([-2, 5]); + } + + await core.requestAction({ + componentName: "/addPoint", + actionName: "callAction", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/p3"].stateValues.latex)).eq("(3,4)"); + + g1 = stateVariables["/theGraphs/g"]; + g2 = stateVariables["/theGraphs/g2"]; + g3 = stateVariables["/theGraphs2/g"]; + g4 = stateVariables["/theGraphs2/g2"]; + gs = [g1, g2, g3, g4]; + + for (let g of gs) { + let pointNames = g.stateValues.graphicalDescendants.map( + (x) => x.componentName, + ); + expect(pointNames.length).eq(3); + expect( + stateVariables[pointNames[0]].stateValues.xs.map((x) => x.tree), + ).eqls([1, 2]); + expect( + stateVariables[pointNames[1]].stateValues.xs.map((x) => x.tree), + ).eqls([-2, 5]); + expect( + stateVariables[pointNames[2]].stateValues.xs.map((x) => x.tree), + ).eqls([3, 4]); + } + + await core.requestAction({ + actionName: "movePoint", + componentName: g2.stateValues.graphicalDescendants[2].componentName, + args: { x: 7, y: -9 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/p3"].stateValues.latex)).eq( + "(7,-9)", + ); + + g1 = stateVariables["/theGraphs/g"]; + g2 = stateVariables["/theGraphs/g2"]; + g3 = stateVariables["/theGraphs2/g"]; + g4 = stateVariables["/theGraphs2/g2"]; + gs = [g1, g2, g3, g4]; + + for (let g of gs) { + let pointNames = g.stateValues.graphicalDescendants.map( + (x) => x.componentName, + ); + expect( + stateVariables[pointNames[2]].stateValues.xs.map((x) => x.tree), + ).eqls([7, -9]); + } + + await core.requestAction({ + componentName: "/deletePoint", + actionName: "callAction", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p3"]).eq(undefined); + + g1 = stateVariables["/theGraphs/g"]; + g2 = stateVariables["/theGraphs/g2"]; + g3 = stateVariables["/theGraphs2/g"]; + g4 = stateVariables["/theGraphs2/g2"]; + gs = [g1, g2, g3, g4]; + + for (let g of gs) { + let pointNames = g.stateValues.graphicalDescendants.map( + (x) => x.componentName, + ); + expect(pointNames.length).eq(2); + expect( + stateVariables[pointNames[0]].stateValues.xs.map((x) => x.tree), + ).eqls([1, 2]); + expect( + stateVariables[pointNames[1]].stateValues.xs.map((x) => x.tree), + ).eqls([-2, 5]); + } + + await core.requestAction({ + actionName: "movePoint", + componentName: g3.stateValues.graphicalDescendants[1].componentName, + args: { x: 1, y: 0 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/p2"].stateValues.latex)).eq("(1,0)"); + + g1 = stateVariables["/theGraphs/g"]; + g2 = stateVariables["/theGraphs/g2"]; + g3 = stateVariables["/theGraphs2/g"]; + g4 = stateVariables["/theGraphs2/g2"]; + gs = [g1, g2, g3, g4]; + + for (let g of gs) { + let pointNames = g.stateValues.graphicalDescendants.map( + (x) => x.componentName, + ); + expect( + stateVariables[pointNames[1]].stateValues.xs.map((x) => x.tree), + ).eqls([1, 0]); + } + + await core.requestAction({ + componentName: "/deletePoint", + actionName: "callAction", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p2"]).eq(undefined); + + g1 = stateVariables["/theGraphs/g"]; + g2 = stateVariables["/theGraphs/g2"]; + g3 = stateVariables["/theGraphs2/g"]; + g4 = stateVariables["/theGraphs2/g2"]; + gs = [g1, g2, g3, g4]; + + for (let g of gs) { + let pointNames = g.stateValues.graphicalDescendants.map( + (x) => x.componentName, + ); + expect(pointNames.length).eq(1); + expect( + stateVariables[pointNames[0]].stateValues.xs.map((x) => x.tree), + ).eqls([1, 2]); + } + + await core.requestAction({ + componentName: "/deletePoint", + actionName: "callAction", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/p1"].stateValues.latex)).eq("(1,2)"); + + g1 = stateVariables["/theGraphs/g"]; + g2 = stateVariables["/theGraphs/g2"]; + g3 = stateVariables["/theGraphs2/g"]; + g4 = stateVariables["/theGraphs2/g2"]; + gs = [g1, g2, g3, g4]; + + for (let g of gs) { + let pointNames = g.stateValues.graphicalDescendants.map( + (x) => x.componentName, + ); + expect(pointNames.length).eq(1); + expect( + stateVariables[pointNames[0]].stateValues.xs.map((x) => x.tree), + ).eqls([1, 2]); + } + + await core.requestAction({ + componentName: "/addPoint", + actionName: "callAction", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/p2"].stateValues.latex)).eq("(3,4)"); + + g1 = stateVariables["/theGraphs/g"]; + g2 = stateVariables["/theGraphs/g2"]; + g3 = stateVariables["/theGraphs2/g"]; + g4 = stateVariables["/theGraphs2/g2"]; + gs = [g1, g2, g3, g4]; + + for (let g of gs) { + let pointNames = g.stateValues.graphicalDescendants.map( + (x) => x.componentName, + ); + expect(pointNames.length).eq(2); + expect( + stateVariables[pointNames[0]].stateValues.xs.map((x) => x.tree), + ).eqls([1, 2]); + expect( + stateVariables[pointNames[1]].stateValues.xs.map((x) => x.tree), + ).eqls([3, 4]); + } + }); + + async function test_chained_actions(core) { + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/addPoint"].stateValues.hidden).eq(true); + + expect(stateVariables["/g"].stateValues.graphicalDescendants.length).eq( + 1, + ); + + let numbers = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers.length).eq(5); + for (let num of numbers) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + + await core.requestAction({ + componentName: "/rs", + actionName: "callAction", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/p2"].stateValues.latex)).eq("(3,4)"); + + let pointNames = stateVariables[ + "/g" + ].stateValues.graphicalDescendants.map((x) => x.componentName); + expect(pointNames.length).eq(2); + expect( + stateVariables[pointNames[0]].stateValues.xs.map((x) => x.tree), + ).eqls([1, 2]); + expect( + stateVariables[pointNames[1]].stateValues.xs.map((x) => x.tree), + ).eqls([3, 4]); + + await core.requestAction({ + actionName: "movePoint", + componentName: pointNames[1], + args: { x: -2, y: 5 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/p2"].stateValues.latex)).eq( + "(-2,5)", + ); + + pointNames = stateVariables["/g"].stateValues.graphicalDescendants.map( + (x) => x.componentName, + ); + expect( + stateVariables[pointNames[1]].stateValues.xs.map((x) => x.tree), + ).eqls([-2, 5]); + + let numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + + expect(numbers2.length).eq(5); + for (let num of numbers2) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + expect(numbers2).not.eqls(numbers); + } + + it("chained actions", async () => { + let core = await createTestCore({ + doenetML: ` +

+

+ +

+ + + (1,2) + + +

points from graph:

+ + + + (3,4) + + + `, + }); + + await test_chained_actions(core); + }); + + it("chained actions, unnecessary $", async () => { + let core = await createTestCore({ + doenetML: ` +

+

+ +

+ + + (1,2) + + +

points from graph:

+ + + + (3,4) + + + `, + }); + + await test_chained_actions(core); + }); + + it("chained actions, inside map", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + `, + }); + + for (let ind = 1; ind <= 2; ind++) { + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables[`/set${ind}/addPoint`].stateValues.hidden).eq( + true, + ); + + expect( + stateVariables[`/set${ind}/g`].stateValues.graphicalDescendants + .length, + ).eq(1); + + let numbers = stateVariables[`/set${ind}/nums`].stateValues.text + .split(",") + .map(Number); + expect(numbers.length).eq(5); + for (let num of numbers) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + + await core.requestAction({ + componentName: `/set${ind}/rs`, + actionName: "callAction", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables[`/set${ind}/p2`].stateValues.latex), + ).eq("(3,4)"); + + let pointNames = stateVariables[ + `/set${ind}/g` + ].stateValues.graphicalDescendants.map((x) => x.componentName); + expect(pointNames.length).eq(2); + expect( + stateVariables[pointNames[0]].stateValues.xs.map((x) => x.tree), + ).eqls([1, 2]); + expect( + stateVariables[pointNames[1]].stateValues.xs.map((x) => x.tree), + ).eqls([3, 4]); + + await core.requestAction({ + actionName: "movePoint", + componentName: pointNames[1], + args: { x: -2, y: 5 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables[`/set${ind}/p2`].stateValues.latex), + ).eq("(-2,5)"); + + pointNames = stateVariables[ + `/set${ind}/g` + ].stateValues.graphicalDescendants.map((x) => x.componentName); + expect( + stateVariables[pointNames[1]].stateValues.xs.map((x) => x.tree), + ).eqls([-2, 5]); + + let numbers2 = stateVariables[`/set${ind}/nums`].stateValues.text + .split(",") + .map(Number); + + expect(numbers2.length).eq(5); + for (let num of numbers2) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + expect(numbers2).not.eqls(numbers); + } + }); + + it("chained actions on multiple sources", async () => { + let core = await createTestCore({ + doenetML: ` +

+

+ +

+ +

1

+

+ +

+ + + (1,2) + + +

points from graph:

+ + + + (3,4) + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/addPoint"].stateValues.hidden).eq(true); + + expect(stateVariables["/g"].stateValues.graphicalDescendants.length).eq( + 1, + ); + + let numbers = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers.length).eq(5); + for (let num of numbers) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + + expect(stateVariables["/n"].stateValues.value).eq(1); + + await core.requestAction({ + componentName: "/rs", + actionName: "callAction", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/p2"].stateValues.latex)).eq("(3,4)"); + + let pointNames = stateVariables[ + "/g" + ].stateValues.graphicalDescendants.map((x) => x.componentName); + expect(pointNames.length).eq(2); + expect( + stateVariables[pointNames[0]].stateValues.xs.map((x) => x.tree), + ).eqls([1, 2]); + expect( + stateVariables[pointNames[1]].stateValues.xs.map((x) => x.tree), + ).eqls([3, 4]); + + await core.requestAction({ + actionName: "movePoint", + componentName: pointNames[1], + args: { x: -2, y: 5 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/p2"].stateValues.latex)).eq( + "(-2,5)", + ); + + pointNames = stateVariables["/g"].stateValues.graphicalDescendants.map( + (x) => x.componentName, + ); + expect( + stateVariables[pointNames[1]].stateValues.xs.map((x) => x.tree), + ).eqls([-2, 5]); + + let numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + + expect(numbers2.length).eq(5); + for (let num of numbers2) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + expect(numbers2).not.eqls(numbers); + + expect(stateVariables["/n"].stateValues.value).eq(1); + + await core.requestAction({ + componentName: "/in", + actionName: "updateValue", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/p3"].stateValues.latex)).eq("(3,4)"); + + pointNames = stateVariables["/g"].stateValues.graphicalDescendants.map( + (x) => x.componentName, + ); + expect(pointNames.length).eq(3); + expect( + stateVariables[pointNames[0]].stateValues.xs.map((x) => x.tree), + ).eqls([1, 2]); + expect( + stateVariables[pointNames[1]].stateValues.xs.map((x) => x.tree), + ).eqls([-2, 5]); + expect( + stateVariables[pointNames[2]].stateValues.xs.map((x) => x.tree), + ).eqls([3, 4]); + + await core.requestAction({ + actionName: "movePoint", + componentName: pointNames[2], + args: { x: 7, y: -9 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/p3"].stateValues.latex)).eq( + "(7,-9)", + ); + + pointNames = stateVariables["/g"].stateValues.graphicalDescendants.map( + (x) => x.componentName, + ); + expect( + stateVariables[pointNames[2]].stateValues.xs.map((x) => x.tree), + ).eqls([7, -9]); + + expect(stateVariables["/n"].stateValues.value).eq(2); + }); + + it("action based on trigger", async () => { + let core = await createTestCore({ + doenetML: ` + + (-1,2) + + $P.coords{assignNames="P2"} + +

+

+ +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/rs"].stateValues.hidden).eq(true); + + let numbers = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers.length).eq(5); + for (let num of numbers) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq( + "(-1,2)", + ); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -1, y: -7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq( + "(-1,-7)", + ); + + let numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + + expect(numbers2).eqls(numbers); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 3, y: -4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq( + "(3,-4)", + ); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + + expect(numbers2).eqls(numbers); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 1, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq("(1,7)"); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + + expect(numbers2.length).eq(5); + for (let num of numbers2) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + expect(numbers2).not.eqls(numbers); + numbers = numbers2; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 5, y: 9 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq("(5,9)"); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + + expect(numbers2).eqls(numbers); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -3, y: 4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq( + "(-3,4)", + ); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + + expect(numbers2).eqls(numbers); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -6, y: 5 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq( + "(-6,5)", + ); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + + expect(numbers2).eqls(numbers); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 4, y: 2 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq("(4,2)"); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + + expect(numbers2.length).eq(5); + for (let num of numbers2) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + expect(numbers2).not.eqls(numbers); + numbers = numbers2; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 9, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq("(9,7)"); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + + expect(numbers2).eqls(numbers); + }); + + it("action triggered when click", async () => { + let core = await createTestCore({ + doenetML: ` + + (-1,2) + + $P.coords{assignNames="P2"} + +

+

+ +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/rs"].stateValues.hidden).eq(true); + + let numbers = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers.length).eq(5); + for (let num of numbers) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq( + "(-1,2)", + ); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 3, y: -4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq( + "(3,-4)", + ); + + let numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + + expect(numbers2).eqls(numbers); + + await core.requestAction({ + actionName: "pointClicked", + componentName: "/P", + args: { name: "/P" }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + + expect(numbers2.length).eq(5); + for (let num of numbers2) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + expect(numbers2).not.eqls(numbers); + numbers = numbers2; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 5, y: 9 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq("(5,9)"); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + + expect(numbers2).eqls(numbers); + + await core.requestAction({ + actionName: "pointClicked", + componentName: "/P", + args: { name: "/P" }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + + expect(numbers2.length).eq(5); + for (let num of numbers2) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + expect(numbers2).not.eqls(numbers); + numbers = numbers2; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 9, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq("(9,7)"); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + + expect(numbers2).eqls(numbers); + }); + + it("action triggered when click, inside template creating random names", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + for (let ind = 0; ind < 2; ind++) { + let templateName = + stateVariables["/_map1"].replacements![ind].componentName; + + let tReps = stateVariables[templateName].replacements; + let graphName = tReps![1].componentName; + let copyName = tReps![3].componentName; + let numsName = tReps![5].componentName; + + let PName = + stateVariables[graphName].activeChildren[0].componentName; + let P2Name = + stateVariables[copyName].replacements![0].componentName; + + let numbers = stateVariables[numsName].stateValues.text + .split(",") + .map(Number); + expect(numbers.length).eq(5); + for (let num of numbers) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + + expect(cleanLatex(stateVariables[P2Name].stateValues.latex)).eq( + "(-1,2)", + ); + + await core.requestAction({ + actionName: "movePoint", + componentName: PName, + args: { x: 3, y: -4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables[P2Name].stateValues.latex)).eq( + "(3,-4)", + ); + + let numbers2 = stateVariables[numsName].stateValues.text + .split(",") + .map(Number); + + expect(numbers2).eqls(numbers); + + await core.requestAction({ + actionName: "pointClicked", + componentName: PName, + args: { name: PName }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + numbers2 = stateVariables[numsName].stateValues.text + .split(",") + .map(Number); + + expect(numbers2.length).eq(5); + for (let num of numbers2) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + expect(numbers2).not.eqls(numbers); + numbers = numbers2; + + await core.requestAction({ + actionName: "movePoint", + componentName: PName, + args: { x: 5, y: 9 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables[P2Name].stateValues.latex)).eq( + "(5,9)", + ); + + numbers2 = stateVariables[numsName].stateValues.text + .split(",") + .map(Number); + + expect(numbers2).eqls(numbers); + + await core.requestAction({ + actionName: "pointClicked", + componentName: PName, + args: { name: PName }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + numbers2 = stateVariables[numsName].stateValues.text + .split(",") + .map(Number); + + expect(numbers2.length).eq(5); + for (let num of numbers2) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + expect(numbers2).not.eqls(numbers); + numbers = numbers2; + + await core.requestAction({ + actionName: "movePoint", + componentName: PName, + args: { x: 9, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables[P2Name].stateValues.latex)).eq( + "(9,7)", + ); + + numbers2 = stateVariables[numsName].stateValues.text + .split(",") + .map(Number); + + expect(numbers2).eqls(numbers); + } + }); + + it("action triggered when object focused", async () => { + let core = await createTestCore({ + doenetML: ` + + (-1,2) + + $P.coords{assignNames="P2"} + +

+

+ +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/rs"].stateValues.hidden).eq(true); + + let numbers = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers.length).eq(5); + for (let num of numbers) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq( + "(-1,2)", + ); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 3, y: -4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq( + "(3,-4)", + ); + + let numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + + expect(numbers2).eqls(numbers); + + await core.requestAction({ + actionName: "pointFocused", + componentName: "/P", + args: { name: "/P" }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + + expect(numbers2.length).eq(5); + for (let num of numbers2) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + expect(numbers2).not.eqls(numbers); + numbers = numbers2; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 5, y: 9 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq("(5,9)"); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + + expect(numbers2).eqls(numbers); + + await core.requestAction({ + actionName: "pointFocused", + componentName: "/P", + args: { name: "/P" }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + + expect(numbers2.length).eq(5); + for (let num of numbers2) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + expect(numbers2).not.eqls(numbers); + numbers = numbers2; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 9, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq("(9,7)"); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + + expect(numbers2).eqls(numbers); + }); + + it("chained updates based on trigger", async () => { + let core = await createTestCore({ + doenetML: ` + + (-1,2) + + $P.coords{assignNames="P2"} + +

+

+ +

+ + + + (3,4) + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/rs"].stateValues.hidden).eq(true); + expect(stateVariables["/addPoint"].stateValues.hidden).eq(true); + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq( + "(-1,2)", + ); + expect(stateVariables["/g"].stateValues.graphicalDescendants.length).eq( + 1, + ); + + let numbers = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers.length).eq(5); + for (let num of numbers) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -1, y: -7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq( + "(-1,-7)", + ); + + expect(stateVariables["/g"].stateValues.graphicalDescendants.length).eq( + 1, + ); + + let numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers2).eqls(numbers); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 3, y: -4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq( + "(3,-4)", + ); + + expect(stateVariables["/g"].stateValues.graphicalDescendants.length).eq( + 1, + ); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers2).eqls(numbers); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 1, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq("(1,7)"); + + expect(stateVariables["/g"].stateValues.graphicalDescendants.length).eq( + 2, + ); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + + expect(numbers2.length).eq(5); + for (let num of numbers2) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + expect(numbers2).not.eqls(numbers); + numbers = numbers2; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 5, y: 9 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq("(5,9)"); + + expect(stateVariables["/g"].stateValues.graphicalDescendants.length).eq( + 2, + ); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers2).eqls(numbers); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -3, y: 4 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq( + "(-3,4)", + ); + + expect(stateVariables["/g"].stateValues.graphicalDescendants.length).eq( + 2, + ); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers2).eqls(numbers); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -6, y: 5 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq( + "(-6,5)", + ); + + expect(stateVariables["/g"].stateValues.graphicalDescendants.length).eq( + 2, + ); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers2).eqls(numbers); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 4, y: 2 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq("(4,2)"); + + expect(stateVariables["/g"].stateValues.graphicalDescendants.length).eq( + 3, + ); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + + expect(numbers2.length).eq(5); + for (let num of numbers2) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + expect(numbers2).not.eqls(numbers); + numbers = numbers2; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 9, y: 7 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq("(9,7)"); + + expect(stateVariables["/g"].stateValues.graphicalDescendants.length).eq( + 3, + ); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers2).eqls(numbers); + }); + + it("triggerWhen supersedes chaining", async () => { + let core = await createTestCore({ + doenetML: ` + + (-1,2) + + + $P.coords{assignNames="P2"} + +

+

+ +

+ + + + (3,4) + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/rs"].stateValues.hidden).eq(true); + expect(stateVariables["/addPoint"].stateValues.hidden).eq(true); + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq( + "(-1,2)", + ); + expect(stateVariables["/g"].stateValues.graphicalDescendants.length).eq( + 1, + ); + + let numbers = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers.length).eq(5); + for (let num of numbers) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -1, y: -7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq( + "(-1,-7)", + ); + + expect(stateVariables["/g"].stateValues.graphicalDescendants.length).eq( + 1, + ); + + let numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers2.length).eq(5); + for (let num of numbers2) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + expect(numbers2).not.eqls(numbers); + numbers = numbers2; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 3, y: -4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq( + "(3,-4)", + ); + + expect(stateVariables["/g"].stateValues.graphicalDescendants.length).eq( + 1, + ); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers2).eqls(numbers); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 1, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq("(1,7)"); + + expect(stateVariables["/g"].stateValues.graphicalDescendants.length).eq( + 2, + ); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers2).eqls(numbers); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 5, y: 9 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq("(5,9)"); + + expect(stateVariables["/g"].stateValues.graphicalDescendants.length).eq( + 2, + ); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers2).eqls(numbers); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -3, y: -4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq( + "(-3,-4)", + ); + + expect(stateVariables["/g"].stateValues.graphicalDescendants.length).eq( + 2, + ); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers2.length).eq(5); + for (let num of numbers2) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + expect(numbers2).not.eqls(numbers); + numbers = numbers2; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -6, y: -5 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq( + "(-6,-5)", + ); + + expect(stateVariables["/g"].stateValues.graphicalDescendants.length).eq( + 2, + ); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers2).eqls(numbers); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 4, y: 2 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq("(4,2)"); + + expect(stateVariables["/g"].stateValues.graphicalDescendants.length).eq( + 3, + ); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers2).eqls(numbers); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 9, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/P2"].stateValues.latex)).eq("(9,7)"); + + expect(stateVariables["/g"].stateValues.graphicalDescendants.length).eq( + 3, + ); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers2).eqls(numbers); + }); + + it("triggerSet", async () => { + let core = await createTestCore({ + doenetML: ` + + (1,2) + + +

points from graph:

+ +

+ + + + + + + + + (3,4) + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/rs"].stateValues.hidden).eq(true); + expect(stateVariables["/addPoint"].stateValues.hidden).eq(true); + + expect(stateVariables["/g"].stateValues.graphicalDescendants.length).eq( + 1, + ); + + let numbers = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers.length).eq(5); + for (let num of numbers) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + + await core.requestAction({ + actionName: "triggerActions", + componentName: "/tset", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/p2"].stateValues.latex)).eq("(3,4)"); + + let pointNames = stateVariables[ + "/g" + ].stateValues.graphicalDescendants.map((x) => x.componentName); + expect(pointNames.length).eq(2); + expect( + stateVariables[pointNames[0]].stateValues.xs.map((x) => x.tree), + ).eqls([1, 2]); + expect( + stateVariables[pointNames[1]].stateValues.xs.map((x) => x.tree), + ).eqls([3, 4]); + + await core.requestAction({ + actionName: "movePoint", + componentName: pointNames[1], + args: { x: -2, y: 5 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/p2"].stateValues.latex)).eq( + "(-2,5)", + ); + + pointNames = stateVariables["/g"].stateValues.graphicalDescendants.map( + (x) => x.componentName, + ); + expect( + stateVariables[pointNames[1]].stateValues.xs.map((x) => x.tree), + ).eqls([-2, 5]); + + let numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers2.length).eq(5); + for (let num of numbers2) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + expect(numbers2).not.eqls(numbers); + }); + + it("triggerSet and chain to callAction", async () => { + let core = await createTestCore({ + doenetML: ` + + (1,2) + + +

points from graph:

+ +

+ +

Enter x: x

+ + + + + + + + + (3,4) + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/rs"].stateValues.hidden).eq(true); + expect(stateVariables["/addPoint"].stateValues.hidden).eq(true); + expect(stateVariables["/sub"].stateValues.hidden).eq(true); + + let mathInputName = + stateVariables["/ans"].stateValues.inputChildren[0].componentName; + + await updateMathInputValue({ + latex: "x", + componentName: mathInputName, + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/ans"].stateValues.justSubmitted).eq(false); + + expect(stateVariables["/g"].stateValues.graphicalDescendants.length).eq( + 1, + ); + + let numbers = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers.length).eq(5); + for (let num of numbers) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + + await core.requestAction({ + actionName: "triggerActions", + componentName: "/tset", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/p2"].stateValues.latex)).eq("(3,4)"); + + let pointNames = stateVariables[ + "/g" + ].stateValues.graphicalDescendants.map((x) => x.componentName); + expect(pointNames.length).eq(2); + expect( + stateVariables[pointNames[0]].stateValues.xs.map((x) => x.tree), + ).eqls([1, 2]); + expect( + stateVariables[pointNames[1]].stateValues.xs.map((x) => x.tree), + ).eqls([3, 4]); + + await core.requestAction({ + actionName: "movePoint", + componentName: pointNames[1], + args: { x: -2, y: 5 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/p2"].stateValues.latex)).eq( + "(-2,5)", + ); + + pointNames = stateVariables["/g"].stateValues.graphicalDescendants.map( + (x) => x.componentName, + ); + expect( + stateVariables[pointNames[1]].stateValues.xs.map((x) => x.tree), + ).eqls([-2, 5]); + + let numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers2.length).eq(5); + for (let num of numbers2) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + expect(numbers2).not.eqls(numbers); + + expect(stateVariables["/ans"].stateValues.justSubmitted).eq(true); + expect(stateVariables["/ans"].stateValues.creditAchieved).eq(1); + }); + + it("chaining with updateValue", async () => { + let core = await createTestCore({ + doenetML: ` +

+

+ +

+ + + (1,2) + + +

points from graph:

+ + + + (3,4) + + +

Count: 1

+ + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/addPoint"].stateValues.hidden).eq(true); + + expect(stateVariables["/g"].stateValues.graphicalDescendants.length).eq( + 1, + ); + + let numbers = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers.length).eq(5); + for (let num of numbers) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + + expect(stateVariables["/n"].stateValues.value).eq(1); + + await core.requestAction({ + componentName: "/rs", + actionName: "callAction", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/p2"].stateValues.latex)).eq("(3,4)"); + + let pointNames = stateVariables[ + "/g" + ].stateValues.graphicalDescendants.map((x) => x.componentName); + expect(pointNames.length).eq(2); + expect( + stateVariables[pointNames[0]].stateValues.xs.map((x) => x.tree), + ).eqls([1, 2]); + expect( + stateVariables[pointNames[1]].stateValues.xs.map((x) => x.tree), + ).eqls([3, 4]); + + await core.requestAction({ + actionName: "movePoint", + componentName: pointNames[1], + args: { x: -2, y: 5 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/p2"].stateValues.latex)).eq( + "(-2,5)", + ); + + pointNames = stateVariables["/g"].stateValues.graphicalDescendants.map( + (x) => x.componentName, + ); + expect( + stateVariables[pointNames[1]].stateValues.xs.map((x) => x.tree), + ).eqls([-2, 5]); + + let numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers2.length).eq(5); + for (let num of numbers2) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + expect(numbers2).not.eqls(numbers); + + expect(stateVariables["/n"].stateValues.value).eq(2); + }); + + it("math in label", async () => { + let core = await createTestCore({ + doenetML: ` +

+

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/rs"].stateValues.label).eq( + "Hi \\(\\sum_{i=1}^5x_i\\)", + ); + }); + + it("label is name", async () => { + let core = await createTestCore({ + doenetML: ` +

+

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/resample_numbers"].stateValues.label).eq( + "resample numbers", + ); + }); + + it("case insensitive action name", async () => { + let core = await createTestCore({ + doenetML: ` +

+

+

Sum: + + + $s + +

+ `, + }); + + await test_resample(core); + }); + + it("callAction in graph", async () => { + let core = await createTestCore({ + doenetML: ` + + + + (3,4) + + + + (-3,-4) + + + +

Anchor 1 coordinates: $callAction1.anchor

+

Anchor 2 coordinates: $callAction2.anchor

+

Change anchor 1 coordinates:

+

Change anchor 2 coordinates:

+

Position from anchor 1: $callAction1.positionFromAnchor

+

Position from anchor 2: $callAction2.positionFromAnchor

+

Change position from anchor 1 + + upperRight + upperLeft + lowerRight + lowerLeft + left + right + top + bottom + center + +

+

Change position from anchor 2 + + upperRight + upperLeft + lowerRight + lowerLeft + left + right + top + bottom + center + +

+

Draggable 1: $draggable1

+

Draggable 2: $draggable2

+

Change draggable 1

+

Change draggable 2

+

Disabled 1: $disabled1

+

Disabled 2: $disabled2

+

Change disabled 1

+

Change disabled 2

+

Fixed 1: $fixed1

+

Fixed 2: $fixed2

+

Change fixed 1

+

Change fixed 2

+

FixLocation 1: $fixLocation1

+

FixLocation 2: $fixLocation2

+

Change fixLocation 1

+

Change fixLocation 2

+ + `, + }); + + // TODO: how to click on the buttons and test if they are disabled? + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/pAnchor1"].stateValues.text).eq( + "Anchor 1 coordinates: ( 1, 3 )", + ); + expect(stateVariables["/pAnchor2"].stateValues.text).eq( + "Anchor 2 coordinates: ( 0, 0 )", + ); + expect(stateVariables["/pPositionFromAnchor1"].stateValues.text).eq( + "Position from anchor 1: upperright", + ); + expect(stateVariables["/pPositionFromAnchor2"].stateValues.text).eq( + "Position from anchor 2: center", + ); + expect( + stateVariables["/positionFromAnchor1"].stateValues.selectedIndices, + ).eqls([1]); + expect( + stateVariables["/positionFromAnchor2"].stateValues.selectedIndices, + ).eqls([9]); + expect(stateVariables["/pDraggable1"].stateValues.text).eq( + "Draggable 1: true", + ); + expect(stateVariables["/pDraggable2"].stateValues.text).eq( + "Draggable 2: true", + ); + expect(stateVariables["/pDisabled1"].stateValues.text).eq( + "Disabled 1: true", + ); + expect(stateVariables["/pDisabled2"].stateValues.text).eq( + "Disabled 2: false", + ); + expect(stateVariables["/pFixed1"].stateValues.text).eq( + "Fixed 1: false", + ); + expect(stateVariables["/pFixed2"].stateValues.text).eq( + "Fixed 2: false", + ); + expect(stateVariables["/pFixLocation1"].stateValues.text).eq( + "FixLocation 1: false", + ); + expect(stateVariables["/pFixLocation2"].stateValues.text).eq( + "FixLocation 2: false", + ); + + // move callActions by dragging + + await core.requestAction({ + actionName: "moveButton", + componentName: "/callAction1", + args: { x: -2, y: 3 }, + event: null, + }); + await core.requestAction({ + actionName: "moveButton", + componentName: "/callAction2", + args: { x: 4, y: -5 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/pAnchor1"].stateValues.text).eq( + "Anchor 1 coordinates: ( -2, 3 )", + ); + expect(stateVariables["/pAnchor2"].stateValues.text).eq( + "Anchor 2 coordinates: ( 4, -5 )", + ); + + // move callActions by entering coordinates + + await updateMathInputValue({ + latex: "(6,7)", + componentName: "/anchorCoords1", + core, + }); + await updateMathInputValue({ + latex: "(8,9)", + componentName: "/anchorCoords2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/pAnchor1"].stateValues.text).eq( + "Anchor 1 coordinates: ( 6, 7 )", + ); + expect(stateVariables["/pAnchor2"].stateValues.text).eq( + "Anchor 2 coordinates: ( 8, 9 )", + ); + + // change position from anchor + await core.requestAction({ + componentName: "/positionFromAnchor1", + actionName: "updateSelectedIndices", + args: { + selectedIndices: [4], + }, + event: null, + }); + await core.requestAction({ + componentName: "/positionFromAnchor2", + actionName: "updateSelectedIndices", + args: { + selectedIndices: [3], + }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pPositionFromAnchor1"].stateValues.text).eq( + "Position from anchor 1: lowerleft", + ); + expect(stateVariables["/pPositionFromAnchor2"].stateValues.text).eq( + "Position from anchor 2: lowerright", + ); + + // make not draggable + await updateBooleanInputValue({ + boolean: false, + componentName: "/draggable1", + core, + }); + await updateBooleanInputValue({ + boolean: false, + componentName: "/draggable2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pDraggable1"].stateValues.text).eq( + "Draggable 1: false", + ); + expect(stateVariables["/pDraggable2"].stateValues.text).eq( + "Draggable 2: false", + ); + + // cannot move callActions by dragging + await core.requestAction({ + actionName: "moveButton", + componentName: "/callAction1", + args: { x: -10, y: -9 }, + event: null, + }); + await core.requestAction({ + actionName: "moveButton", + componentName: "/callAction2", + args: { x: -8, y: -7 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pAnchor1"].stateValues.text).eq( + "Anchor 1 coordinates: ( 6, 7 )", + ); + expect(stateVariables["/pAnchor2"].stateValues.text).eq( + "Anchor 2 coordinates: ( 8, 9 )", + ); + + // make draggable again + await updateBooleanInputValue({ + boolean: true, + componentName: "/draggable1", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/draggable2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pDraggable1"].stateValues.text).eq( + "Draggable 1: true", + ); + expect(stateVariables["/pDraggable2"].stateValues.text).eq( + "Draggable 2: true", + ); + + await core.requestAction({ + actionName: "moveButton", + componentName: "/callAction1", + args: { x: -10, y: -9 }, + event: null, + }); + await core.requestAction({ + actionName: "moveButton", + componentName: "/callAction2", + args: { x: -8, y: -7 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pAnchor1"].stateValues.text).eq( + "Anchor 1 coordinates: ( -10, -9 )", + ); + expect(stateVariables["/pAnchor2"].stateValues.text).eq( + "Anchor 2 coordinates: ( -8, -7 )", + ); + + // fix location + await updateBooleanInputValue({ + boolean: true, + componentName: "/fixLocation1", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/fixLocation2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pFixLocation1"].stateValues.text).eq( + "FixLocation 1: true", + ); + expect(stateVariables["/pFixLocation2"].stateValues.text).eq( + "FixLocation 2: true", + ); + + // can change coordinates entering coordinates only for button 1 + await updateMathInputValue({ + latex: "(1,2)", + componentName: "/anchorCoords1", + core, + }); + await updateMathInputValue({ + latex: "(3,4)", + componentName: "/anchorCoords2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pAnchor1"].stateValues.text).eq( + "Anchor 1 coordinates: ( 1, 2 )", + ); + expect(stateVariables["/pAnchor2"].stateValues.text).eq( + "Anchor 2 coordinates: ( -8, -7 )", + ); + + // cannot move callActions by dragging + await core.requestAction({ + actionName: "moveButton", + componentName: "/callAction1", + args: { x: 4, y: 6 }, + event: null, + }); + await core.requestAction({ + actionName: "moveButton", + componentName: "/callAction2", + args: { x: 7, y: 8 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pAnchor1"].stateValues.text).eq( + "Anchor 1 coordinates: ( 1, 2 )", + ); + expect(stateVariables["/pAnchor2"].stateValues.text).eq( + "Anchor 2 coordinates: ( -8, -7 )", + ); + + // can change position from anchor only for button 1 + await core.requestAction({ + componentName: "/positionFromAnchor1", + actionName: "updateSelectedIndices", + args: { + selectedIndices: [7], + }, + event: null, + }); + await core.requestAction({ + componentName: "/positionFromAnchor2", + actionName: "updateSelectedIndices", + args: { + selectedIndices: [8], + }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pPositionFromAnchor1"].stateValues.text).eq( + "Position from anchor 1: top", + ); + expect(stateVariables["/pPositionFromAnchor2"].stateValues.text).eq( + "Position from anchor 2: lowerright", + ); + + // can change disabled attribute + + await updateBooleanInputValue({ + boolean: false, + componentName: "/disabled1", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/disabled2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pDisabled1"].stateValues.text).eq( + "Disabled 1: false", + ); + expect(stateVariables["/pDisabled2"].stateValues.text).eq( + "Disabled 2: true", + ); + + // make completely fixed + + await updateBooleanInputValue({ + boolean: true, + componentName: "/fixed1", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/fixed2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pFixed1"].stateValues.text).eq("Fixed 1: true"); + expect(stateVariables["/pFixed2"].stateValues.text).eq("Fixed 2: true"); + + // can change coordinates entering coordinates only for button 1 + await updateMathInputValue({ + latex: "(5,6)", + componentName: "/anchorCoords1", + core, + }); + await updateMathInputValue({ + latex: "(7,8)", + componentName: "/anchorCoords2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pAnchor1"].stateValues.text).eq( + "Anchor 1 coordinates: ( 5, 6 )", + ); + expect(stateVariables["/pAnchor2"].stateValues.text).eq( + "Anchor 2 coordinates: ( -8, -7 )", + ); + + // can change position from anchor only for button 1 + await core.requestAction({ + componentName: "/positionFromAnchor1", + actionName: "updateSelectedIndices", + args: { + selectedIndices: [6], + }, + event: null, + }); + await core.requestAction({ + componentName: "/positionFromAnchor2", + actionName: "updateSelectedIndices", + args: { + selectedIndices: [5], + }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pPositionFromAnchor1"].stateValues.text).eq( + "Position from anchor 1: right", + ); + expect(stateVariables["/pPositionFromAnchor2"].stateValues.text).eq( + "Position from anchor 2: lowerright", + ); + + // can change disabled attribute only for button 1 + + await updateBooleanInputValue({ + boolean: true, + componentName: "/disabled1", + core, + }); + await updateBooleanInputValue({ + boolean: false, + componentName: "/disabled2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pDisabled1"].stateValues.text).eq( + "Disabled 1: true", + ); + expect(stateVariables["/pDisabled2"].stateValues.text).eq( + "Disabled 2: true", + ); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/collect.test.ts b/packages/doenetml-worker/src/test/tagSpecific/collect.test.ts new file mode 100644 index 000000000..fe4a46064 --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/collect.test.ts @@ -0,0 +1,2906 @@ +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"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +describe("Collect tag tests", async () => { + it("collect points from graphs", async () => { + let core = await createTestCore({ + doenetML: ` + + + (-3,1) + (-7,5) + + + + $_point1{name="p1a"} + (4,2) + + (, + ) + + + + + + + + +

Coordinates of points:

+

x-coordinates of points:

+

x-coordinates of points via a copy:

+

x-coordinates of points via extract:

+

Average of y-coordinates of points:

+ `, + }); + + let x1 = -3, + y1 = 1; + let x2 = -7, + y2 = 5; + let x3 = 4, + y3 = 2; + + let coords1Text = ("(" + x1 + "," + y1 + ")").replace(/-/g, "−"); + let coords2Text = ("(" + x2 + "," + y2 + ")").replace(/-/g, "−"); + let coords3Text = ("(" + x3 + "," + y3 + ")").replace(/-/g, "−"); + let coords2tText = ("(" + y2 + "," + x2 + ")").replace(/-/g, "−"); + + let meany = (y1 + y2 + y1 + y3 + x2) / 5; + + let xs = [x1, x2, x1, x3, y2]; + let ys = [y1, y2, y1, y3, x2]; + let stateVariables = await returnAllStateVariables(core); + for (let i = 0; i < 5; i++) { + expect(stateVariables[`/q${i + 1}`].stateValues.xs[0].tree).eq( + xs[i], + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[1].tree).eq( + ys[i], + ); + expect(stateVariables[`/qa${i + 1}`].stateValues.xs[0].tree).eq( + xs[i], + ); + expect(stateVariables[`/qa${i + 1}`].stateValues.xs[1].tree).eq( + ys[i], + ); + expect(stateVariables[`/c${i + 1}`].stateValues.value.tree).eqls([ + "vector", + xs[i], + ys[i], + ]); + expect(stateVariables[`/x${i + 1}`].stateValues.value.tree).eq( + xs[i], + ); + expect(stateVariables[`/xc${i + 1}`].stateValues.value.tree).eq( + xs[i], + ); + expect(stateVariables[`/xe${i + 1}`].stateValues.value.tree).eq( + xs[i], + ); + expect(stateVariables[`/y${i + 1}`].stateValues.value.tree).eq( + ys[i], + ); + } + expect(stateVariables["/mean"].stateValues.value.tree).eq(meany); + + // move point 1 + x1 = -8; + y1 = 6; + xs = [x1, x2, x1, x3, y2]; + ys = [y1, y2, y1, y3, x2]; + meany = (y1 + y2 + y1 + y3 + x2) / 5; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/_point1", + args: { x: x1, y: y1 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + for (let i = 0; i < 5; i++) { + expect(stateVariables[`/q${i + 1}`].stateValues.xs[0].tree).eq( + xs[i], + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[1].tree).eq( + ys[i], + ); + expect(stateVariables[`/qa${i + 1}`].stateValues.xs[0].tree).eq( + xs[i], + ); + expect(stateVariables[`/qa${i + 1}`].stateValues.xs[1].tree).eq( + ys[i], + ); + expect(stateVariables[`/c${i + 1}`].stateValues.value.tree).eqls([ + "vector", + xs[i], + ys[i], + ]); + expect(stateVariables[`/x${i + 1}`].stateValues.value.tree).eq( + xs[i], + ); + expect(stateVariables[`/xc${i + 1}`].stateValues.value.tree).eq( + xs[i], + ); + expect(stateVariables[`/xe${i + 1}`].stateValues.value.tree).eq( + xs[i], + ); + expect(stateVariables[`/y${i + 1}`].stateValues.value.tree).eq( + ys[i], + ); + } + expect(stateVariables["/mean"].stateValues.value.tree).eq(meany); + + // move point 1 via copy + x1 = 2; + y1 = 0; + xs = [x1, x2, x1, x3, y2]; + ys = [y1, y2, y1, y3, x2]; + meany = (y1 + y2 + y1 + y3 + x2) / 5; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/p1a", + args: { x: x1, y: y1 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + for (let i = 0; i < 5; i++) { + expect(stateVariables[`/q${i + 1}`].stateValues.xs[0].tree).eq( + xs[i], + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[1].tree).eq( + ys[i], + ); + expect(stateVariables[`/qa${i + 1}`].stateValues.xs[0].tree).eq( + xs[i], + ); + expect(stateVariables[`/qa${i + 1}`].stateValues.xs[1].tree).eq( + ys[i], + ); + expect(stateVariables[`/c${i + 1}`].stateValues.value.tree).eqls([ + "vector", + xs[i], + ys[i], + ]); + expect(stateVariables[`/x${i + 1}`].stateValues.value.tree).eq( + xs[i], + ); + expect(stateVariables[`/xc${i + 1}`].stateValues.value.tree).eq( + xs[i], + ); + expect(stateVariables[`/xe${i + 1}`].stateValues.value.tree).eq( + xs[i], + ); + expect(stateVariables[`/y${i + 1}`].stateValues.value.tree).eq( + ys[i], + ); + } + expect(stateVariables["/mean"].stateValues.value.tree).eq(meany); + + // move point 2 + x2 = 4; + y2 = 8; + xs = [x1, x2, x1, x3, y2]; + ys = [y1, y2, y1, y3, x2]; + meany = (y1 + y2 + y1 + y3 + x2) / 5; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/_point2", + args: { x: x2, y: y2 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + for (let i = 0; i < 5; i++) { + expect(stateVariables[`/q${i + 1}`].stateValues.xs[0].tree).eq( + xs[i], + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[1].tree).eq( + ys[i], + ); + expect(stateVariables[`/qa${i + 1}`].stateValues.xs[0].tree).eq( + xs[i], + ); + expect(stateVariables[`/qa${i + 1}`].stateValues.xs[1].tree).eq( + ys[i], + ); + expect(stateVariables[`/c${i + 1}`].stateValues.value.tree).eqls([ + "vector", + xs[i], + ys[i], + ]); + expect(stateVariables[`/x${i + 1}`].stateValues.value.tree).eq( + xs[i], + ); + expect(stateVariables[`/xc${i + 1}`].stateValues.value.tree).eq( + xs[i], + ); + expect(stateVariables[`/xe${i + 1}`].stateValues.value.tree).eq( + xs[i], + ); + expect(stateVariables[`/y${i + 1}`].stateValues.value.tree).eq( + ys[i], + ); + } + expect(stateVariables["/mean"].stateValues.value.tree).eq(meany); + + // move flipped point 2 + x2 = -1; + y2 = -3; + xs = [x1, x2, x1, x3, y2]; + ys = [y1, y2, y1, y3, x2]; + meany = (y1 + y2 + y1 + y3 + x2) / 5; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/_point4", + args: { x: y2, y: x2 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + for (let i = 0; i < 5; i++) { + expect(stateVariables[`/q${i + 1}`].stateValues.xs[0].tree).eq( + xs[i], + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[1].tree).eq( + ys[i], + ); + expect(stateVariables[`/qa${i + 1}`].stateValues.xs[0].tree).eq( + xs[i], + ); + expect(stateVariables[`/qa${i + 1}`].stateValues.xs[1].tree).eq( + ys[i], + ); + expect(stateVariables[`/c${i + 1}`].stateValues.value.tree).eqls([ + "vector", + xs[i], + ys[i], + ]); + expect(stateVariables[`/x${i + 1}`].stateValues.value.tree).eq( + xs[i], + ); + expect(stateVariables[`/xc${i + 1}`].stateValues.value.tree).eq( + xs[i], + ); + expect(stateVariables[`/xe${i + 1}`].stateValues.value.tree).eq( + xs[i], + ); + expect(stateVariables[`/y${i + 1}`].stateValues.value.tree).eq( + ys[i], + ); + } + expect(stateVariables["/mean"].stateValues.value.tree).eq(meany); + + // move point 3 + x3 = -5; + y3 = 9; + xs = [x1, x2, x1, x3, y2]; + ys = [y1, y2, y1, y3, x2]; + meany = (y1 + y2 + y1 + y3 + x2) / 5; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/_point3", + args: { x: x3, y: y3 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + for (let i = 0; i < 5; i++) { + expect(stateVariables[`/q${i + 1}`].stateValues.xs[0].tree).eq( + xs[i], + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[1].tree).eq( + ys[i], + ); + expect(stateVariables[`/qa${i + 1}`].stateValues.xs[0].tree).eq( + xs[i], + ); + expect(stateVariables[`/qa${i + 1}`].stateValues.xs[1].tree).eq( + ys[i], + ); + expect(stateVariables[`/c${i + 1}`].stateValues.value.tree).eqls([ + "vector", + xs[i], + ys[i], + ]); + expect(stateVariables[`/x${i + 1}`].stateValues.value.tree).eq( + xs[i], + ); + expect(stateVariables[`/xc${i + 1}`].stateValues.value.tree).eq( + xs[i], + ); + expect(stateVariables[`/xe${i + 1}`].stateValues.value.tree).eq( + xs[i], + ); + expect(stateVariables[`/y${i + 1}`].stateValues.value.tree).eq( + ys[i], + ); + } + expect(stateVariables["/mean"].stateValues.value.tree).eq(meany); + }); + + it("collect dynamic points from graphs", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + y=x/3 + + + + + + + + + + + + + + + +

y-coordinates of points: + +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(3); + expect( + stateVariables["/_collect1"].stateValues.collectedComponents.length, + ).eq(3); + expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(3); + expect( + stateVariables["/_collect2"].stateValues.collectedComponents.length, + ).eq(6); + expect( + stateVariables["/_collect3"].stateValues.collectedComponents.length, + ).eq(6); + + for (let i = 0; i < 3; i++) { + let x = i + 1; + expect(stateVariables[`/p${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/p${i + 1}`].stateValues.xs[1].tree).eq( + 2 * x, + ); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1].tree).eq( + 2 * x, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[1].tree).eq( + 3 * x, + ); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[1].tree).eq( + 2 * x, + ); + expect(stateVariables[`/r${i + 4}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/r${i + 4}`].stateValues.xs[1].tree).eq( + 3 * x, + ); + expect(stateVariables[`/y${i + 1}`].stateValues.value.tree).eq( + 2 * x, + ); + expect(stateVariables[`/y${i + 4}`].stateValues.value.tree).eq( + 3 * x, + ); + } + + // increase number of points + await updateMathInputValue({ + latex: "5", + componentName: "/length", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(5); + expect( + stateVariables["/_collect1"].stateValues.collectedComponents.length, + ).eq(5); + expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(5); + expect( + stateVariables["/_collect2"].stateValues.collectedComponents.length, + ).eq(10); + expect( + stateVariables["/_collect3"].stateValues.collectedComponents.length, + ).eq(10); + + for (let i = 0; i < 5; i++) { + let x = i + 1; + expect(stateVariables[`/p${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/p${i + 1}`].stateValues.xs[1].tree).eq( + 2 * x, + ); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1].tree).eq( + 2 * x, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[1].tree).eq( + 3 * x, + ); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[1].tree).eq( + 2 * x, + ); + expect(stateVariables[`/r${i + 6}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/r${i + 6}`].stateValues.xs[1].tree).eq( + 3 * x, + ); + expect(stateVariables[`/y${i + 1}`].stateValues.value.tree).eq( + 2 * x, + ); + expect(stateVariables[`/y${i + 6}`].stateValues.value.tree).eq( + 3 * x, + ); + } + + // change multiple + await updateMathInputValue({ + latex: "0.5", + componentName: "/mult", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(5); + expect( + stateVariables["/_collect1"].stateValues.collectedComponents.length, + ).eq(5); + expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(5); + expect( + stateVariables["/_collect2"].stateValues.collectedComponents.length, + ).eq(10); + expect( + stateVariables["/_collect3"].stateValues.collectedComponents.length, + ).eq(10); + + for (let i = 0; i < 5; i++) { + let x = i + 1; + expect(stateVariables[`/p${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/p${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[1].tree).eq( + 0.75 * x, + ); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/r${i + 6}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/r${i + 6}`].stateValues.xs[1].tree).eq( + 0.75 * x, + ); + expect(stateVariables[`/y${i + 1}`].stateValues.value.tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/y${i + 6}`].stateValues.value.tree).eq( + 0.75 * x, + ); + } + + // decrease number of points + await updateMathInputValue({ + latex: "1", + componentName: "/length", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(1); + expect( + stateVariables["/_collect1"].stateValues.collectedComponents.length, + ).eq(1); + expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(1); + expect( + stateVariables["/_collect2"].stateValues.collectedComponents.length, + ).eq(2); + expect( + stateVariables["/_collect3"].stateValues.collectedComponents.length, + ).eq(2); + + for (let i = 0; i < 1; i++) { + let x = i + 1; + expect(stateVariables[`/p${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/p${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[1].tree).eq( + 0.75 * x, + ); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/r${i + 2}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/r${i + 2}`].stateValues.xs[1].tree).eq( + 0.75 * x, + ); + expect(stateVariables[`/y${i + 1}`].stateValues.value.tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/y${i + 2}`].stateValues.value.tree).eq( + 0.75 * x, + ); + } + + // increase number of points back to 4 + await updateMathInputValue({ + latex: "4", + componentName: "/length", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(4); + expect( + stateVariables["/_collect1"].stateValues.collectedComponents.length, + ).eq(4); + expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(4); + expect( + stateVariables["/_collect2"].stateValues.collectedComponents.length, + ).eq(8); + expect( + stateVariables["/_collect3"].stateValues.collectedComponents.length, + ).eq(8); + + for (let i = 0; i < 4; i++) { + let x = i + 1; + expect(stateVariables[`/p${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/p${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[1].tree).eq( + 0.75 * x, + ); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/r${i + 5}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/r${i + 5}`].stateValues.xs[1].tree).eq( + 0.75 * x, + ); + expect(stateVariables[`/y${i + 1}`].stateValues.value.tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/y${i + 5}`].stateValues.value.tree).eq( + 0.75 * x, + ); + } + + // increase number of points to 6 + await updateMathInputValue({ + latex: "6", + componentName: "/length", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(6); + expect( + stateVariables["/_collect1"].stateValues.collectedComponents.length, + ).eq(6); + expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(6); + expect( + stateVariables["/_collect2"].stateValues.collectedComponents.length, + ).eq(12); + expect( + stateVariables["/_collect3"].stateValues.collectedComponents.length, + ).eq(12); + + for (let i = 0; i < 6; i++) { + let x = i + 1; + expect(stateVariables[`/p${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/p${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[1].tree).eq( + 0.75 * x, + ); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/r${i + 7}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/r${i + 7}`].stateValues.xs[1].tree).eq( + 0.75 * x, + ); + expect(stateVariables[`/y${i + 1}`].stateValues.value.tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/y${i + 7}`].stateValues.value.tree).eq( + 0.75 * x, + ); + } + }); + + it("collect dynamic points from groups", async () => { + let core = await createTestCore({ + doenetML: ` + + +
+ + + + + + y=x/3 + + + + + + + + + +
+ + + + + +

y-coordinates of points: + +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(3); + expect( + stateVariables["/_collect1"].stateValues.collectedComponents.length, + ).eq(3); + expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(3); + expect( + stateVariables["/_collect2"].stateValues.collectedComponents.length, + ).eq(6); + expect( + stateVariables["/_collect3"].stateValues.collectedComponents.length, + ).eq(6); + + for (let i = 0; i < 3; i++) { + let x = i + 1; + expect(stateVariables[`/p${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/p${i + 1}`].stateValues.xs[1].tree).eq( + 2 * x, + ); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1].tree).eq( + 2 * x, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[1].tree).eq( + 3 * x, + ); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[1].tree).eq( + 2 * x, + ); + expect(stateVariables[`/r${i + 4}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/r${i + 4}`].stateValues.xs[1].tree).eq( + 3 * x, + ); + expect(stateVariables[`/y${i + 1}`].stateValues.value.tree).eq( + 2 * x, + ); + expect(stateVariables[`/y${i + 4}`].stateValues.value.tree).eq( + 3 * x, + ); + } + + // increase number of points + await updateMathInputValue({ + latex: "5", + componentName: "/length", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(5); + expect( + stateVariables["/_collect1"].stateValues.collectedComponents.length, + ).eq(5); + expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(5); + expect( + stateVariables["/_collect2"].stateValues.collectedComponents.length, + ).eq(10); + expect( + stateVariables["/_collect3"].stateValues.collectedComponents.length, + ).eq(10); + + for (let i = 0; i < 5; i++) { + let x = i + 1; + expect(stateVariables[`/p${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/p${i + 1}`].stateValues.xs[1].tree).eq( + 2 * x, + ); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1].tree).eq( + 2 * x, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[1].tree).eq( + 3 * x, + ); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[1].tree).eq( + 2 * x, + ); + expect(stateVariables[`/r${i + 6}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/r${i + 6}`].stateValues.xs[1].tree).eq( + 3 * x, + ); + expect(stateVariables[`/y${i + 1}`].stateValues.value.tree).eq( + 2 * x, + ); + expect(stateVariables[`/y${i + 6}`].stateValues.value.tree).eq( + 3 * x, + ); + } + + // change multiple + await updateMathInputValue({ + latex: "0.5", + componentName: "/mult", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(5); + expect( + stateVariables["/_collect1"].stateValues.collectedComponents.length, + ).eq(5); + expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(5); + expect( + stateVariables["/_collect2"].stateValues.collectedComponents.length, + ).eq(10); + expect( + stateVariables["/_collect3"].stateValues.collectedComponents.length, + ).eq(10); + + for (let i = 0; i < 5; i++) { + let x = i + 1; + expect(stateVariables[`/p${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/p${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[1].tree).eq( + 0.75 * x, + ); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/r${i + 6}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/r${i + 6}`].stateValues.xs[1].tree).eq( + 0.75 * x, + ); + expect(stateVariables[`/y${i + 1}`].stateValues.value.tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/y${i + 6}`].stateValues.value.tree).eq( + 0.75 * x, + ); + } + + // decrease number of points + await updateMathInputValue({ + latex: "1", + componentName: "/length", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(1); + expect( + stateVariables["/_collect1"].stateValues.collectedComponents.length, + ).eq(1); + expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(1); + expect( + stateVariables["/_collect2"].stateValues.collectedComponents.length, + ).eq(2); + expect( + stateVariables["/_collect3"].stateValues.collectedComponents.length, + ).eq(2); + + for (let i = 0; i < 1; i++) { + let x = i + 1; + expect(stateVariables[`/p${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/p${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[1].tree).eq( + 0.75 * x, + ); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/r${i + 2}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/r${i + 2}`].stateValues.xs[1].tree).eq( + 0.75 * x, + ); + expect(stateVariables[`/y${i + 1}`].stateValues.value.tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/y${i + 2}`].stateValues.value.tree).eq( + 0.75 * x, + ); + } + + // increase number of points back to 4 + await updateMathInputValue({ + latex: "4", + componentName: "/length", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(4); + expect( + stateVariables["/_collect1"].stateValues.collectedComponents.length, + ).eq(4); + expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(4); + expect( + stateVariables["/_collect2"].stateValues.collectedComponents.length, + ).eq(8); + expect( + stateVariables["/_collect3"].stateValues.collectedComponents.length, + ).eq(8); + + for (let i = 0; i < 4; i++) { + let x = i + 1; + expect(stateVariables[`/p${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/p${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[1].tree).eq( + 0.75 * x, + ); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/r${i + 5}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/r${i + 5}`].stateValues.xs[1].tree).eq( + 0.75 * x, + ); + expect(stateVariables[`/y${i + 1}`].stateValues.value.tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/y${i + 5}`].stateValues.value.tree).eq( + 0.75 * x, + ); + } + + // increase number of points to 6 + await updateMathInputValue({ + latex: "6", + componentName: "/length", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(6); + expect( + stateVariables["/_collect1"].stateValues.collectedComponents.length, + ).eq(6); + expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(6); + expect( + stateVariables["/_collect2"].stateValues.collectedComponents.length, + ).eq(12); + expect( + stateVariables["/_collect3"].stateValues.collectedComponents.length, + ).eq(12); + + for (let i = 0; i < 6; i++) { + let x = i + 1; + expect(stateVariables[`/p${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/p${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[1].tree).eq( + 0.75 * x, + ); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/r${i + 7}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/r${i + 7}`].stateValues.xs[1].tree).eq( + 0.75 * x, + ); + expect(stateVariables[`/y${i + 1}`].stateValues.value.tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/y${i + 7}`].stateValues.value.tree).eq( + 0.75 * x, + ); + } + }); + + it("collect points and vectors from graphs", async () => { + let core = await createTestCore({ + doenetML: ` + + + (-3,1) + (-7,4) + + + + + + (, + ) + + + (, + ) + + + + + + + + + + $_vector1.head.map(x=>x.tree){assignNames="h1"} + $_vector2.head.map(x=>x.tree){assignNames="h2"} + `, + }); + + let x1 = -3, + y1 = 1; + let x2 = -7, + y2 = 4; + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_point1"].stateValues.coords.tree).eqls([ + "vector", + x1, + y1, + ]); + expect(stateVariables["/_point2"].stateValues.coords.tree).eqls([ + "vector", + x2, + y2, + ]); + expect( + stateVariables["/_vector1"].stateValues.tail.map((x) => x.tree), + ).eqls([x1, y1]); + expect( + stateVariables["/_vector1"].stateValues.head.map((x) => x.tree), + ).eqls([x2, y2]); + expect(stateVariables["/_point3"].stateValues.coords.tree).eqls([ + "vector", + y1, + x1, + ]); + expect(stateVariables["/_point4"].stateValues.coords.tree).eqls([ + "vector", + y2, + x2, + ]); + expect( + stateVariables["/_vector2"].stateValues.tail.map((x) => x.tree), + ).eqls([y1, x1]); + expect( + stateVariables["/_vector2"].stateValues.head.map((x) => x.tree), + ).eqls([y2, x2]); + expect( + stateVariables["/_collect1"].stateValues.collectedComponents.length, + ).eq(6); + expect(stateVariables["/v1"].stateValues.coords.tree).eqls([ + "vector", + x1, + y1, + ]); + expect(stateVariables["/v2"].stateValues.coords.tree).eqls([ + "vector", + x2, + y2, + ]); + expect(stateVariables["/v3"].stateValues.tail.map((x) => x.tree)).eqls([ + x1, + y1, + ]); + expect(stateVariables["/v3"].stateValues.head.map((x) => x.tree)).eqls([ + x2, + y2, + ]); + expect(stateVariables["/v4"].stateValues.coords.tree).eqls([ + "vector", + y1, + x1, + ]); + expect(stateVariables["/v5"].stateValues.coords.tree).eqls([ + "vector", + y2, + x2, + ]); + expect(stateVariables["/v6"].stateValues.tail.map((x) => x.tree)).eqls([ + y1, + x1, + ]); + expect(stateVariables["/v6"].stateValues.head.map((x) => x.tree)).eqls([ + y2, + x2, + ]); + + // move vector 1 via copy + x1 = -8; + y1 = 6; + x2 = 3; + y2 = 2; + + await core.requestAction({ + actionName: "moveVector", + componentName: "/v3", + args: { tailcoords: [x1, y1], headcoords: [x2, y2] }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_point1"].stateValues.coords.tree).eqls([ + "vector", + x1, + y1, + ]); + expect(stateVariables["/_point2"].stateValues.coords.tree).eqls([ + "vector", + x2, + y2, + ]); + expect( + stateVariables["/_vector1"].stateValues.tail.map((x) => x.tree), + ).eqls([x1, y1]); + expect( + stateVariables["/_vector1"].stateValues.head.map((x) => x.tree), + ).eqls([x2, y2]); + expect(stateVariables["/_point3"].stateValues.coords.tree).eqls([ + "vector", + y1, + x1, + ]); + expect(stateVariables["/_point4"].stateValues.coords.tree).eqls([ + "vector", + y2, + x2, + ]); + expect( + stateVariables["/_vector2"].stateValues.tail.map((x) => x.tree), + ).eqls([y1, x1]); + expect( + stateVariables["/_vector2"].stateValues.head.map((x) => x.tree), + ).eqls([y2, x2]); + expect( + stateVariables["/_collect1"].stateValues.collectedComponents.length, + ).eq(6); + expect(stateVariables["/v1"].stateValues.coords.tree).eqls([ + "vector", + x1, + y1, + ]); + expect(stateVariables["/v2"].stateValues.coords.tree).eqls([ + "vector", + x2, + y2, + ]); + expect(stateVariables["/v3"].stateValues.tail.map((x) => x.tree)).eqls([ + x1, + y1, + ]); + expect(stateVariables["/v3"].stateValues.head.map((x) => x.tree)).eqls([ + x2, + y2, + ]); + expect(stateVariables["/v4"].stateValues.coords.tree).eqls([ + "vector", + y1, + x1, + ]); + expect(stateVariables["/v5"].stateValues.coords.tree).eqls([ + "vector", + y2, + x2, + ]); + expect(stateVariables["/v6"].stateValues.tail.map((x) => x.tree)).eqls([ + y1, + x1, + ]); + expect(stateVariables["/v6"].stateValues.head.map((x) => x.tree)).eqls([ + y2, + x2, + ]); + + // move vector 2 via copy + x1 = 9; + y1 = 0; + x2 = -7; + y2 = 5; + + await core.requestAction({ + actionName: "moveVector", + componentName: "/v6", + args: { tailcoords: [y1, x1], headcoords: [y2, x2] }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_point1"].stateValues.coords.tree).eqls([ + "vector", + x1, + y1, + ]); + expect(stateVariables["/_point2"].stateValues.coords.tree).eqls([ + "vector", + x2, + y2, + ]); + expect( + stateVariables["/_vector1"].stateValues.tail.map((x) => x.tree), + ).eqls([x1, y1]); + expect( + stateVariables["/_vector1"].stateValues.head.map((x) => x.tree), + ).eqls([x2, y2]); + expect(stateVariables["/_point3"].stateValues.coords.tree).eqls([ + "vector", + y1, + x1, + ]); + expect(stateVariables["/_point4"].stateValues.coords.tree).eqls([ + "vector", + y2, + x2, + ]); + expect( + stateVariables["/_vector2"].stateValues.tail.map((x) => x.tree), + ).eqls([y1, x1]); + expect( + stateVariables["/_vector2"].stateValues.head.map((x) => x.tree), + ).eqls([y2, x2]); + expect( + stateVariables["/_collect1"].stateValues.collectedComponents.length, + ).eq(6); + expect(stateVariables["/v1"].stateValues.coords.tree).eqls([ + "vector", + x1, + y1, + ]); + expect(stateVariables["/v2"].stateValues.coords.tree).eqls([ + "vector", + x2, + y2, + ]); + expect(stateVariables["/v3"].stateValues.tail.map((x) => x.tree)).eqls([ + x1, + y1, + ]); + expect(stateVariables["/v3"].stateValues.head.map((x) => x.tree)).eqls([ + x2, + y2, + ]); + expect(stateVariables["/v4"].stateValues.coords.tree).eqls([ + "vector", + y1, + x1, + ]); + expect(stateVariables["/v5"].stateValues.coords.tree).eqls([ + "vector", + y2, + x2, + ]); + expect(stateVariables["/v6"].stateValues.tail.map((x) => x.tree)).eqls([ + y1, + x1, + ]); + expect(stateVariables["/v6"].stateValues.head.map((x) => x.tree)).eqls([ + y2, + x2, + ]); + }); + + it("maximum number", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + + y=x/3 + + + + + + + + + + + + + + + +

y-coordinates of points: + +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(5); + expect( + stateVariables["/_collect1"].stateValues.collectedComponents.length, + ).eq(2); + expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(2); + expect( + stateVariables["/_collect2"].stateValues.collectedComponents.length, + ).eq(4); + expect( + stateVariables["/_collect3"].stateValues.collectedComponents.length, + ).eq(2); + + for (let i = 0; i < 5; i++) { + let x = i + 1; + expect(stateVariables[`/p${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/p${i + 1}`].stateValues.xs[1].tree).eq( + 2 * x, + ); + } + for (let i = 0; i < 2; i++) { + let x = i + 1; + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1].tree).eq( + 2 * x, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[1].tree).eq( + 3 * x, + ); + } + for (let i = 0; i < 4; i++) { + let x = i + 1; + expect(stateVariables[`/r${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[1].tree).eq( + 2 * x, + ); + } + for (let i = 0; i < 2; i++) { + let x = i + 1; + expect(stateVariables[`/y${i + 1}`].stateValues.value.tree).eq( + 2 * x, + ); + } + + // increase maxnumber + await updateMathInputValue({ + latex: "5", + componentName: "/maxnumber", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(5); + expect( + stateVariables["/_collect1"].stateValues.collectedComponents.length, + ).eq(5); + expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(5); + expect( + stateVariables["/_collect2"].stateValues.collectedComponents.length, + ).eq(10); + expect( + stateVariables["/_collect3"].stateValues.collectedComponents.length, + ).eq(5); + + for (let i = 0; i < 5; i++) { + let x = i + 1; + expect(stateVariables[`/p${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/p${i + 1}`].stateValues.xs[1].tree).eq( + 2 * x, + ); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1].tree).eq( + 2 * x, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[1].tree).eq( + 3 * x, + ); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[1].tree).eq( + 2 * x, + ); + expect(stateVariables[`/r${i + 6}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/r${i + 6}`].stateValues.xs[1].tree).eq( + 3 * x, + ); + expect(stateVariables[`/y${i + 1}`].stateValues.value.tree).eq( + 2 * x, + ); + //expect(stateVariables[`/y${i + 6}`].stateValues.value.tree).eq(3 * x); + } + + // increase maxnumber further + await updateMathInputValue({ + latex: "10", + componentName: "/maxnumber", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(5); + expect( + stateVariables["/_collect1"].stateValues.collectedComponents.length, + ).eq(5); + expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(5); + expect( + stateVariables["/_collect2"].stateValues.collectedComponents.length, + ).eq(10); + expect( + stateVariables["/_collect3"].stateValues.collectedComponents.length, + ).eq(10); + + for (let i = 0; i < 5; i++) { + let x = i + 1; + expect(stateVariables[`/p${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/p${i + 1}`].stateValues.xs[1].tree).eq( + 2 * x, + ); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1].tree).eq( + 2 * x, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[1].tree).eq( + 3 * x, + ); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[1].tree).eq( + 2 * x, + ); + expect(stateVariables[`/r${i + 6}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/r${i + 6}`].stateValues.xs[1].tree).eq( + 3 * x, + ); + expect(stateVariables[`/y${i + 1}`].stateValues.value.tree).eq( + 2 * x, + ); + expect(stateVariables[`/y${i + 6}`].stateValues.value.tree).eq( + 3 * x, + ); + } + + // change multiple + await updateMathInputValue({ + latex: "0.5", + componentName: "/mult", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(5); + expect( + stateVariables["/_collect1"].stateValues.collectedComponents.length, + ).eq(5); + expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(5); + expect( + stateVariables["/_collect2"].stateValues.collectedComponents.length, + ).eq(10); + expect( + stateVariables["/_collect3"].stateValues.collectedComponents.length, + ).eq(10); + + for (let i = 0; i < 5; i++) { + let x = i + 1; + expect(stateVariables[`/p${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/p${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[1].tree).eq( + 0.75 * x, + ); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/r${i + 6}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/r${i + 6}`].stateValues.xs[1].tree).eq( + 0.75 * x, + ); + expect(stateVariables[`/y${i + 1}`].stateValues.value.tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/y${i + 6}`].stateValues.value.tree).eq( + 0.75 * x, + ); + } + + // decrease number of points + await updateMathInputValue({ + latex: "1", + componentName: "/length", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(1); + expect( + stateVariables["/_collect1"].stateValues.collectedComponents.length, + ).eq(1); + expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(1); + expect( + stateVariables["/_collect2"].stateValues.collectedComponents.length, + ).eq(2); + expect( + stateVariables["/_collect3"].stateValues.collectedComponents.length, + ).eq(2); + + for (let i = 0; i < 1; i++) { + let x = i + 1; + expect(stateVariables[`/p${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/p${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[1].tree).eq( + 0.75 * x, + ); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/r${i + 2}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/r${i + 2}`].stateValues.xs[1].tree).eq( + 0.75 * x, + ); + expect(stateVariables[`/y${i + 1}`].stateValues.value.tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/y${i + 2}`].stateValues.value.tree).eq( + 0.75 * x, + ); + } + + // increase number of points back to 4 + await updateMathInputValue({ + latex: "4", + componentName: "/length", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(4); + expect( + stateVariables["/_collect1"].stateValues.collectedComponents.length, + ).eq(4); + expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(4); + expect( + stateVariables["/_collect2"].stateValues.collectedComponents.length, + ).eq(8); + expect( + stateVariables["/_collect3"].stateValues.collectedComponents.length, + ).eq(8); + + for (let i = 0; i < 4; i++) { + let x = i + 1; + expect(stateVariables[`/p${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/p${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[1].tree).eq( + 0.75 * x, + ); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/r${i + 5}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/r${i + 5}`].stateValues.xs[1].tree).eq( + 0.75 * x, + ); + expect(stateVariables[`/y${i + 1}`].stateValues.value.tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/y${i + 5}`].stateValues.value.tree).eq( + 0.75 * x, + ); + } + + // decrease max number to 3 + await updateMathInputValue({ + latex: "3", + componentName: "/maxnumber", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(4); + expect( + stateVariables["/_collect1"].stateValues.collectedComponents.length, + ).eq(3); + expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(3); + expect( + stateVariables["/_collect2"].stateValues.collectedComponents.length, + ).eq(6); + expect( + stateVariables["/_collect3"].stateValues.collectedComponents.length, + ).eq(3); + + for (let i = 0; i < 4; i++) { + let x = i + 1; + expect(stateVariables[`/p${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/p${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + } + for (let i = 0; i < 3; i++) { + let x = i + 1; + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[1].tree).eq( + 0.75 * x, + ); + } + for (let i = 0; i < 4; i++) { + let x = i + 1; + + expect(stateVariables[`/r${i + 1}`].stateValues.xs[0].tree).eq(x); + expect(stateVariables[`/r${i + 1}`].stateValues.xs[1].tree).eq( + 0.5 * x, + ); + } + for (let i = 0; i < 2; i++) { + let x = i + 1; + expect(stateVariables[`/r${i + 5}`].stateValues.xs[0].tree).eq( + x + 1, + ); + expect(stateVariables[`/r${i + 5}`].stateValues.xs[1].tree).eq( + 0.75 * x, + ); + } + for (let i = 0; i < 3; i++) { + let x = i + 1; + expect(stateVariables[`/y${i + 1}`].stateValues.value.tree).eq( + 0.5 * x, + ); + } + }); + + it("collect, extract, copy multiple ways", async () => { + let core = await createTestCore({ + doenetML: ` +

How many blanks? + +

+ +

Enter expressions: + + + + + + +

+ +

Inputs collected then, values extracted: +

+ +

Copied:

+

Copy aslist:

+

Copy copied: $values1a

+

Copy aslist containing copy: $al1a

+

Copy copied aslist: $al1b

+ +

Values collected: +

+ +

Copied:

+

Copy aslist:

+

Copy copied: $values2a

+

Copy aslist containing copy: $al2a

+

Copy copied aslist: $al2b

+ +

+ Inputs collected: + + + +

+ +

+ Copied: + + + +

+

Copy aslist:

+

+ Copy copied: $cola{assignNames="mic1 mic2 mic3 mic4 mic5"} +

+

Copy aslist containing copy: $al3a{name="al3d" newNamespace}

+

Copy copied aslist: $al3b{name="al3e"}

+ + `, + }); + + async function set_and_check_items(values, mis_used = "orig") { + await updateMathInputValue({ + latex: `${values.length}`, + componentName: "/n", + core, + }); + + for (let [ind, val] of values.entries()) { + let mi_name; + if (mis_used === "orig") { + mi_name = `/mi${ind + 1}`; + } else if ((mis_used = "col")) { + mi_name = `/micol${ind + 1}`; + } else if ((mis_used = "a")) { + mi_name = `/mia${ind + 1}`; + } else if ((mis_used = "b")) { + mi_name = `/al3b/micol${ind + 1}`; + } else if ((mis_used = "c")) { + mi_name = `/mic${ind + 1}`; + } else if ((mis_used = "d")) { + mi_name = `/al3d/mia${ind + 1}`; + } else if ((mis_used = "e")) { + mi_name = `/al3e/micol${ind + 1}`; + } + + await updateMathInputValue({ + latex: val, + componentName: mi_name, + core, + }); + } + + const stateVariables = await returnAllStateVariables(core); + + const listText = values.join(", "); + + expect(stateVariables["/p_1"].stateValues.text).eq( + `Inputs collected then, values extracted: \n ${listText}`, + ); + expect(stateVariables["/p_1a"].stateValues.text).eq( + `Copied: ${listText}`, + ); + expect(stateVariables["/p_1b"].stateValues.text).eq( + `Copy aslist: ${listText}`, + ); + expect(stateVariables["/p_1c"].stateValues.text).eq( + `Copy copied: ${listText}`, + ); + expect(stateVariables["/p_1d"].stateValues.text).eq( + `Copy aslist containing copy: ${listText}`, + ); + expect(stateVariables["/p_1e"].stateValues.text).eq( + `Copy copied aslist: ${listText}`, + ); + + expect(stateVariables["/p_2"].stateValues.text).eq( + `Values collected: \n ${listText}`, + ); + expect(stateVariables["/p_2a"].stateValues.text).eq( + `Copied: ${listText}`, + ); + expect(stateVariables["/p_2b"].stateValues.text).eq( + `Copy aslist: ${listText}`, + ); + expect(stateVariables["/p_2c"].stateValues.text).eq( + `Copy copied: ${listText}`, + ); + expect(stateVariables["/p_2d"].stateValues.text).eq( + `Copy aslist containing copy: ${listText}`, + ); + expect(stateVariables["/p_2e"].stateValues.text).eq( + `Copy copied aslist: ${listText}`, + ); + + for (let [ind, val] of values.entries()) { + expect( + stateVariables[`/micol${ind + 1}`].stateValues + .immediateValue.tree, + ).eq(val); + expect( + stateVariables[`/mia${ind + 1}`].stateValues.immediateValue + .tree, + ).eq(val); + expect( + stateVariables[`/al3b/micol${ind + 1}`].stateValues + .immediateValue.tree, + ).eq(val); + expect( + stateVariables[`/mic${ind + 1}`].stateValues.immediateValue + .tree, + ).eq(val); + expect( + stateVariables[`/al3d/mia${ind + 1}`].stateValues + .immediateValue.tree, + ).eq(val); + expect( + stateVariables[`/al3e/micol${ind + 1}`].stateValues + .immediateValue.tree, + ).eq(val); + } + } + + await set_and_check_items(["x"]); + + await set_and_check_items(["x1", "y", "z", "u", "v"], "a"); + + await set_and_check_items([]); + + await set_and_check_items(["x2", "y2"], "b"); + + await set_and_check_items(["a", "b"], "c"); + + await set_and_check_items(["e", "f", "g", "h", "i"], "d"); + + await set_and_check_items(["j", "k", "l"], "e"); + }); + + // main point: no longer turn inputs into their value + // even with copy a collection with a macro + it("test macros by collecting inputs and others", async () => { + let core = await createTestCore({ + doenetML: ` +
+ + + + + 2$a + $b there + not $c + + +

+

$_collect1

+

$_group1

+

$_collect1

+

$_group1

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + let group1Replacements = stateVariables["/sec"].activeChildren.slice( + 1, + 14, + ); + + let collect1Replacements = stateVariables["/pcollect1"].activeChildren; + let collect2Replacements = stateVariables["/pcollect2"].activeChildren; + let group2Replacements = stateVariables["/pgroup2"].activeChildren; + let collect3Replacements = stateVariables["/pcollect3"].activeChildren; + let group3Replacements = stateVariables["/pgroup3"].activeChildren; + + expect(group1Replacements.length).eq(13); + expect(collect1Replacements.length).eq(6); + expect(collect2Replacements.length).eq(6); + expect(group2Replacements.length).eq(13); + expect(collect3Replacements.length).eq(6); + expect(group3Replacements.length).eq(13); + + expect(group1Replacements[1].componentType).eq("mathInput"); + expect( + stateVariables[group1Replacements[1].componentName].stateValues + .value.tree, + ).eq("x"); + expect(collect1Replacements[0].componentType).eq("mathInput"); + expect( + stateVariables[collect1Replacements[0].componentName].stateValues + .value.tree, + ).eq("x"); + expect(collect2Replacements[0].componentType).eq("mathInput"); + expect( + stateVariables[collect2Replacements[0].componentName].stateValues + .value.tree, + ).eq("x"); + expect(group2Replacements[1].componentType).eq("mathInput"); + expect( + stateVariables[group2Replacements[1].componentName].stateValues + .value.tree, + ).eq("x"); + expect(collect3Replacements[0].componentType).eq("mathInput"); + expect( + stateVariables[collect3Replacements[0].componentName].stateValues + .value.tree, + ).eq("x"); + expect(group3Replacements[1].componentType).eq("mathInput"); + expect( + stateVariables[group3Replacements[1].componentName].stateValues + .value.tree, + ).eq("x"); + + expect(group1Replacements[3].componentType).eq("textInput"); + expect( + stateVariables[group1Replacements[3].componentName].stateValues + .value, + ).eq("hello"); + expect(collect1Replacements[1].componentType).eq("textInput"); + expect( + stateVariables[collect1Replacements[1].componentName].stateValues + .value, + ).eq("hello"); + expect(collect2Replacements[1].componentType).eq("textInput"); + expect( + stateVariables[collect2Replacements[1].componentName].stateValues + .value, + ).eq("hello"); + expect(group2Replacements[3].componentType).eq("textInput"); + expect( + stateVariables[group2Replacements[3].componentName].stateValues + .value, + ).eq("hello"); + expect(collect3Replacements[1].componentType).eq("textInput"); + expect( + stateVariables[collect3Replacements[1].componentName].stateValues + .value, + ).eq("hello"); + expect(group3Replacements[3].componentType).eq("textInput"); + expect( + stateVariables[group3Replacements[3].componentName].stateValues + .value, + ).eq("hello"); + + expect(group1Replacements[5].componentType).eq("booleanInput"); + expect( + stateVariables[group1Replacements[5].componentName].stateValues + .value, + ).eq(false); + expect(collect1Replacements[2].componentType).eq("booleanInput"); + expect( + stateVariables[collect1Replacements[2].componentName].stateValues + .value, + ).eq(false); + expect(collect2Replacements[2].componentType).eq("booleanInput"); + expect( + stateVariables[collect2Replacements[2].componentName].stateValues + .value, + ).eq(false); + expect(group2Replacements[5].componentType).eq("booleanInput"); + expect( + stateVariables[group2Replacements[5].componentName].stateValues + .value, + ).eq(false); + expect(collect3Replacements[2].componentType).eq("booleanInput"); + expect( + stateVariables[collect3Replacements[2].componentName].stateValues + .value, + ).eq(false); + expect(group3Replacements[5].componentType).eq("booleanInput"); + expect( + stateVariables[group3Replacements[5].componentName].stateValues + .value, + ).eq(false); + + expect(group1Replacements[7].componentType).eq("math"); + expect( + stateVariables[group1Replacements[7].componentName].stateValues + .value.tree, + ).eqls(["*", 2, "x"]); + expect(collect1Replacements[3].componentType).eq("math"); + expect( + stateVariables[collect1Replacements[3].componentName].stateValues + .value.tree, + ).eqls(["*", 2, "x"]); + expect(collect2Replacements[3].componentType).eq("math"); + expect( + stateVariables[collect2Replacements[3].componentName].stateValues + .value.tree, + ).eqls(["*", 2, "x"]); + expect(group2Replacements[7].componentType).eq("math"); + expect( + stateVariables[group2Replacements[7].componentName].stateValues + .value.tree, + ).eqls(["*", 2, "x"]); + expect(collect3Replacements[3].componentType).eq("math"); + expect( + stateVariables[collect3Replacements[3].componentName].stateValues + .value.tree, + ).eqls(["*", 2, "x"]); + expect(group3Replacements[7].componentType).eq("math"); + expect( + stateVariables[group3Replacements[7].componentName].stateValues + .value.tree, + ).eqls(["*", 2, "x"]); + + expect(group1Replacements[9].componentType).eq("text"); + expect( + stateVariables[group1Replacements[9].componentName].stateValues + .value, + ).eq("hello there"); + expect(collect1Replacements[4].componentType).eq("text"); + expect( + stateVariables[collect1Replacements[4].componentName].stateValues + .value, + ).eq("hello there"); + expect(collect2Replacements[4].componentType).eq("text"); + expect( + stateVariables[collect2Replacements[4].componentName].stateValues + .value, + ).eq("hello there"); + expect(group2Replacements[9].componentType).eq("text"); + expect( + stateVariables[group2Replacements[9].componentName].stateValues + .value, + ).eq("hello there"); + expect(collect3Replacements[4].componentType).eq("text"); + expect( + stateVariables[collect3Replacements[4].componentName].stateValues + .value, + ).eq("hello there"); + expect(group3Replacements[9].componentType).eq("text"); + expect( + stateVariables[group3Replacements[9].componentName].stateValues + .value, + ).eq("hello there"); + + expect(group1Replacements[11].componentType).eq("boolean"); + expect( + stateVariables[group1Replacements[11].componentName].stateValues + .value, + ).eq(true); + expect(collect1Replacements[5].componentType).eq("boolean"); + expect( + stateVariables[collect1Replacements[5].componentName].stateValues + .value, + ).eq(true); + expect(collect2Replacements[5].componentType).eq("boolean"); + expect( + stateVariables[collect2Replacements[5].componentName].stateValues + .value, + ).eq(true); + expect(group2Replacements[11].componentType).eq("boolean"); + expect( + stateVariables[group2Replacements[11].componentName].stateValues + .value, + ).eq(true); + expect(collect3Replacements[5].componentType).eq("boolean"); + expect( + stateVariables[collect3Replacements[5].componentName].stateValues + .value, + ).eq(true); + expect(group3Replacements[11].componentType).eq("boolean"); + expect( + stateVariables[group3Replacements[11].componentName].stateValues + .value, + ).eq(true); + }); + + it("collect does not ignore hide", async () => { + let core = await createTestCore({ + doenetML: ` +

+ secret + public +

+

Hidden by default:

+

Force to reveal:

+ + `, + }); + + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p1"].stateValues.text).contain("public"); + expect(stateVariables["/p1"].stateValues.text).not.contain("secret"); + + expect(stateVariables["/p2"].stateValues.text).contain( + "Hidden by default: public", + ); + expect(stateVariables["/p3"].stateValues.text).contain( + "Force to reveal: secret, public", + ); + }); + + it("collect keeps hidden children hidden", async () => { + let core = await createTestCore({ + doenetML: ` +
+

Hidden text: secret

+ $theP1{name="theP2"} +

Hidden paragraph with hidden text: top secret

+ $theP3{name="theP4"} +
+ + + `, + }); + + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/theP1"].stateValues.text).eq("Hidden text: "); + expect(stateVariables["/theP2"].stateValues.text).eq("Hidden text: "); + expect(stateVariables["/theP3"].stateValues.hidden).eq(true); + expect(stateVariables["/theP4"].stateValues.hidden).eq(true); + expect(stateVariables["/cp1"].stateValues.text).eq("Hidden text: "); + expect(stateVariables["/cp2"].stateValues.text).eq("Hidden text: "); + expect(stateVariables["/cp3"].stateValues.hidden).eq(true); + expect(stateVariables["/cp4"].stateValues.hidden).eq(true); + expect(stateVariables["/cp5"].stateValues.text).eq("Hidden text: "); + expect(stateVariables["/cp6"].stateValues.text).eq("Hidden text: "); + expect(stateVariables["/cp7"].stateValues.text).eq( + "Hidden paragraph with hidden text: ", + ); + expect(stateVariables["/cp8"].stateValues.text).eq( + "Hidden paragraph with hidden text: ", + ); + }); + + it("collecting from within a hidden section", async () => { + let core = await createTestCore({ + doenetML: ` +
+

Hidden text: secret

+ $theP1{name="theP2"} +

Hidden paragraph with hidden text: top secret

+ $theP3{name="theP4"} +
+ + + `, + }); + + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/theP1"].stateValues.hidden).eq(true); + expect(stateVariables["/theP2"].stateValues.hidden).eq(true); + expect(stateVariables["/theP3"].stateValues.hidden).eq(true); + expect(stateVariables["/theP4"].stateValues.hidden).eq(true); + expect(stateVariables["/cp1"].stateValues.text).eq("Hidden text: "); + expect(stateVariables["/cp2"].stateValues.text).eq("Hidden text: "); + expect(stateVariables["/cp3"].stateValues.hidden).eq(true); + expect(stateVariables["/cp4"].stateValues.hidden).eq(true); + expect(stateVariables["/cp5"].stateValues.text).eq("Hidden text: "); + expect(stateVariables["/cp6"].stateValues.text).eq("Hidden text: "); + expect(stateVariables["/cp7"].stateValues.text).eq( + "Hidden paragraph with hidden text: ", + ); + expect(stateVariables["/cp8"].stateValues.text).eq( + "Hidden paragraph with hidden text: ", + ); + }); + + it("copies hide dynamically", async () => { + let core = await createTestCore({ + doenetML: ` +

+ + + + +

+ + + + + + + +

Number of points

+ +

collect 1:

+

collect 2:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/c1"].stateValues.text).eq( + "collect 1: Hello, a! Hello, b! Hello, c! Hello, d! ", + ); + expect(stateVariables["/c2"].stateValues.text).eq("collect 2: "); + + await updateMathInputValue({ latex: "6", componentName: "/n", core }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/c1"].stateValues.text).eq( + "collect 1: Hello, a! Hello, b! Hello, c! Hello, d! Hello, e! Hello, f! ", + ); + expect(stateVariables["/c2"].stateValues.text).eq("collect 2: "); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/h1", + core, + }); + await updateBooleanInputValue({ + boolean: false, + componentName: "/h2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/c1"].stateValues.text).eq("collect 1: "); + expect(stateVariables["/c2"].stateValues.text).eq( + "collect 2: Hello, a! Hello, b! Hello, c! Hello, d! Hello, e! Hello, f! ", + ); + + await updateMathInputValue({ latex: "8", componentName: "/n", core }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/c1"].stateValues.text).eq("collect 1: "); + expect(stateVariables["/c2"].stateValues.text).eq( + "collect 2: Hello, a! Hello, b! Hello, c! Hello, d! Hello, e! Hello, f! Hello, g! Hello, h! ", + ); + + await updateBooleanInputValue({ + boolean: false, + componentName: "/h1", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/h2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/c1"].stateValues.text).eq( + "collect 1: Hello, a! Hello, b! Hello, c! Hello, d! Hello, e! Hello, f! Hello, g! Hello, h! ", + ); + expect(stateVariables["/c2"].stateValues.text).eq("collect 2: "); + + await updateMathInputValue({ latex: "3", componentName: "/n", core }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/c1"].stateValues.text).eq( + "collect 1: Hello, a! Hello, b! Hello, c! ", + ); + expect(stateVariables["/c2"].stateValues.text).eq("collect 2: "); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/h1", + core, + }); + await updateBooleanInputValue({ + boolean: false, + componentName: "/h2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/c1"].stateValues.text).eq("collect 1: "); + expect(stateVariables["/c2"].stateValues.text).eq( + "collect 2: Hello, a! Hello, b! Hello, c! ", + ); + + await updateMathInputValue({ latex: "4", componentName: "/n", core }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/c1"].stateValues.text).eq("collect 1: "); + expect(stateVariables["/c2"].stateValues.text).eq( + "collect 2: Hello, a! Hello, b! Hello, c! Hello, d! ", + ); + }); + + it("asList", async () => { + let core = await createTestCore({ + doenetML: ` +

We an apple, a banana, and a cherry.

+ +

+

+ + `, + }); + + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/pdefault"].stateValues.text).eq( + "apple, banana, cherry", + ); + expect(stateVariables["/pnolist"].stateValues.text).eq( + "applebananacherry", + ); + }); + + it("collect warnings", async () => { + let core = await createTestCore({ + doenetML: ` + + + + `, + }); + + let errorWarnings = core.errorWarnings; + + expect(errorWarnings.errors.length).eq(0); + expect(errorWarnings.warnings.length).eq(2); + + expect(errorWarnings.warnings[0].message).contain( + "Cannot collect components of type as it is an invalid component type", + ); + expect(errorWarnings.warnings[0].level).eq(1); + expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(4); + expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(5); + expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(4); + expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(47); + + expect(errorWarnings.warnings[1].message).contain( + "No source found for collect", + ); + expect(errorWarnings.warnings[1].level).eq(1); + expect(errorWarnings.warnings[1].doenetMLrange.lineBegin).eq(3); + expect(errorWarnings.warnings[1].doenetMLrange.charBegin).eq(5); + expect(errorWarnings.warnings[1].doenetMLrange.lineEnd).eq(3); + expect(errorWarnings.warnings[1].doenetMLrange.charEnd).eq(32); + }); + + it("allChildrenOrdered consistent with dynamic collect and adapters", async () => { + let core = await createTestCore({ + doenetML: ` + + +

+ begin + (1,2) + + + + + (3,4) + end +

+ +

Hello there

+ `, + }); + + async function checkAllChildren() { + let stateVariables = await returnAllStateVariables(core); + let components: {} = core.components!; + + let p1AllChildren: string[] = []; + p1AllChildren.push("/A"); + p1AllChildren.push(components["/A"].adapterUsed.componentName); + p1AllChildren.push("/map1"); + + let map = stateVariables["/map1"]; + + let nActiveReps = map.replacements!.length; + if (map.replacementsToWithhold) { + nActiveReps -= + stateVariables["/map1"].replacementsToWithhold || 0; + } + for (let template of map.replacements!.slice(0, nActiveReps)) { + p1AllChildren.push(template.componentName); + let point = components[template.componentName].replacements[0]; + p1AllChildren.push(point.componentName); + p1AllChildren.push(point.adapterUsed.componentName); + } + p1AllChildren.push("/B"); + p1AllChildren.push(components["/B"].adapterUsed.componentName); + + expect(components["/p1"].allChildrenOrdered).eqls(p1AllChildren); + + let p2AllChildren: string[] = []; + p2AllChildren.push("/collect1"); + let collect = stateVariables["/collect1"]; + nActiveReps = collect.replacements!.length; + if (collect.replacementsToWithhold) { + nActiveReps -= + stateVariables["/collect1"].replacementsToWithhold || 0; + } + for (let rep of collect.replacements!.slice(0, nActiveReps)) { + p2AllChildren.push(rep.componentName); + p2AllChildren.push(rep.adapterUsed.componentName); + } + + expect(components["/p2"].allChildrenOrdered).eqls(p2AllChildren); + } + + await checkAllChildren(); + + await updateMathInputValue({ latex: "4", componentName: "/n", core }); + await checkAllChildren(); + + await updateMathInputValue({ latex: "3", componentName: "/n", core }); + await checkAllChildren(); + + await updateMathInputValue({ latex: "1", componentName: "/n", core }); + await checkAllChildren(); + }); + + it("overwrite attributes using collect", async () => { + let core = await createTestCore({ + doenetML: ` +

Collected points are fixed:

+ + + (1,2) + (3,4) + + + + + + + + + + + + `, + }); + + async function check_items(bool: boolean) { + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/A"].stateValues.fixed).eq(false); + expect(stateVariables["/B"].stateValues.fixed).eq(false); + expect(stateVariables["/A2"].stateValues.fixed).eq(bool); + expect(stateVariables["/B2"].stateValues.fixed).eq(bool); + expect(stateVariables["/g3/A2"].stateValues.fixed).eq(bool); + expect(stateVariables["/g3/B2"].stateValues.fixed).eq(bool); + expect(stateVariables["/Ax"].stateValues.fixed).eq(bool); + expect(stateVariables["/Bx"].stateValues.fixed).eq(bool); + expect(stateVariables["/al2/Ax"].stateValues.fixed).eq(bool); + expect(stateVariables["/al2/Bx"].stateValues.fixed).eq(bool); + } + + await check_items(false); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/fixed", + core, + }); + await check_items(true); + + await updateBooleanInputValue({ + boolean: false, + componentName: "/fixed", + core, + }); + await check_items(false); + }); + + it("collect componentIndex", async () => { + let core = await createTestCore({ + doenetML: ` +

n:

+ + + (1,2) + (3,4) + + + + + + + + + + + + + `, + }); + + async function check_items({ + x1, + x2, + y1, + y2, + index, + }: { + x1: number; + x2: number; + y1: number; + y2: number; + index?: number; + }) { + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/A"].stateValues.xs.map((x) => x.tree)).eqls( + [x1, y1], + ); + expect(stateVariables["/B"].stateValues.xs.map((x) => x.tree)).eqls( + [x2, y2], + ); + + if (index) { + const collectX = index === 1 ? x1 : x2; + const collectY = index === 1 ? y1 : y2; + + expect( + stateVariables["/A2"].stateValues.xs.map((x) => x.tree), + ).eqls([collectX, collectY]); + expect( + stateVariables["/g3/A2"].stateValues.xs.map((x) => x.tree), + ).eqls([collectX, collectY]); + + expect(stateVariables["/Ax"].stateValues.value.tree).eq( + collectX, + ); + expect(stateVariables["/al2/Ax"].stateValues.value.tree).eq( + collectX, + ); + } else { + expect(stateVariables["/A2"]).eq(undefined); + expect(stateVariables["/g3/A2"]).eq(undefined); + + expect(stateVariables["/Ax"]).eq(undefined); + expect(stateVariables["/al2/Ax"]).eq(undefined); + } + + expect(stateVariables["/B2"]).eq(undefined); + expect(stateVariables["/g3/B2"]).eq(undefined); + expect(stateVariables["/Bx"]).eq(undefined); + expect(stateVariables["/al2/Bx"]).eq(undefined); + } + + let x1 = 1, + y1 = 2, + x2 = 3, + y2 = 4; + + await check_items({ x1, x2, y1, y2 }); + + // restrict collection to first component + await updateMathInputValue({ latex: "1", componentName: "/n", core }); + await check_items({ x1, x2, y1, y2, index: 1 }); + + // move copied point + x1 = 9; + y1 = -5; + await core.requestAction({ + actionName: "movePoint", + componentName: "/A2", + args: { x: x1, y: y1 }, + event: null, + }); + + await check_items({ x1, x2, y1, y2, index: 1 }); + + // restrict collection to second component + await updateMathInputValue({ latex: "2", componentName: "/n", core }); + await check_items({ x1, x2, y1, y2, index: 2 }); + + // move double copied point + x2 = 0; + y2 = 8; + await core.requestAction({ + actionName: "movePoint", + componentName: "/g3/A2", + args: { x: x2, y: y2 }, + event: null, + }); + await check_items({ x1, x2, y1, y2, index: 2 }); + }); + + it("collect propIndex and componentIndex", async () => { + let core = await createTestCore({ + doenetML: ` +

m:

+

n:

+ + + (1,2) + (3,4) + + +

+ +

+ + `, + }); + + async function check_items({ + x1, + x2, + y1, + y2, + componentIndex, + propIndex, + }: { + x1: number; + x2: number; + y1: number; + y2: number; + componentIndex?: number; + propIndex?: number; + }) { + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/A"].stateValues.xs.map((x) => x.tree)).eqls( + [x1, y1], + ); + expect(stateVariables["/B"].stateValues.xs.map((x) => x.tree)).eqls( + [x2, y2], + ); + + if ( + (componentIndex === 1 || componentIndex === 2) && + (propIndex === 1 || propIndex === 2) + ) { + const val = + componentIndex === 1 + ? propIndex === 1 + ? x1 + : y1 + : propIndex == 1 + ? x2 + : y2; + expect(stateVariables["/n1"].stateValues.value.tree).eq(val); + expect(stateVariables["/al2/n1"].stateValues.value.tree).eq( + val, + ); + } else { + expect(stateVariables["/n1"]).eq(undefined); + expect(stateVariables["/al2/n1"]).eq(undefined); + } + expect(stateVariables["/n2"]).eq(undefined); + expect(stateVariables["/n3"]).eq(undefined); + expect(stateVariables["/n4"]).eq(undefined); + expect(stateVariables["/al2/n2"]).eq(undefined); + expect(stateVariables["/al2/n3"]).eq(undefined); + expect(stateVariables["/al2/n4"]).eq(undefined); + } + + let x1 = 1, + y1 = 2, + x2 = 3, + y2 = 4; + + await check_items({ x1, y1, x2, y2 }); + + // set propIndex to 1 + let propIndex = 1; + await updateMathInputValue({ latex: "1", componentName: "/n", core }); + await check_items({ x1, y1, x2, y2, propIndex }); + + // move point 1 + x1 = 9; + y1 = -5; + await core.requestAction({ + actionName: "movePoint", + componentName: "/A", + args: { x: x1, y: y1 }, + event: null, + }); + await check_items({ x1, y1, x2, y2, propIndex }); + + // set componentIndex to 2 + let componentIndex = 2; + await updateMathInputValue({ latex: "2", componentName: "/m", core }); + await check_items({ x1, y1, x2, y2, propIndex, componentIndex }); + + // move point2 + x2 = 0; + y2 = 8; + await core.requestAction({ + actionName: "movePoint", + componentName: "/B", + args: { x: x2, y: y2 }, + event: null, + }); + await check_items({ x1, y1, x2, y2, propIndex, componentIndex }); + + // set propIndex to 2 + propIndex = 2; + await updateMathInputValue({ latex: "2", componentName: "/n", core }); + await check_items({ x1, y1, x2, y2, propIndex, componentIndex }); + + // set componentIndex to 1 + componentIndex = 1; + await updateMathInputValue({ latex: "1", componentName: "/m", core }); + await check_items({ x1, y1, x2, y2, propIndex, componentIndex }); + + // set propIndex to 3 + propIndex = 3; + await updateMathInputValue({ latex: "3", componentName: "/n", core }); + await check_items({ x1, y1, x2, y2, propIndex, componentIndex }); + + // set propIndex to 1 + propIndex = 3; + await updateMathInputValue({ latex: "3", componentName: "/n", core }); + await check_items({ x1, y1, x2, y2, propIndex, componentIndex }); + + // set componentIndex to 3 + componentIndex = 3; + await updateMathInputValue({ latex: "3", componentName: "/m", core }); + await check_items({ x1, y1, x2, y2, propIndex, componentIndex }); + + // set componentIndex to 2 + componentIndex = 2; + await updateMathInputValue({ latex: "2", componentName: "/m", core }); + await check_items({ x1, y1, x2, y2, propIndex, componentIndex }); + + // clear propIndex + await updateMathInputValue({ latex: "", componentName: "/n", core }); + await check_items({ x1, y1, x2, y2, componentIndex }); + }); + + it("collect prop is case insensitive", async () => { + let core = await createTestCore({ + doenetML: ` + + + (-3,1) + (-7,5) + + + + $_point1{name="p1a"} + (4,2) + + (, + ) + + + + + + + + +

Coordinates of points:

+

x-coordinates of points:

+

x-coordinates of points via a copy:

+

x-coordinates of points via extract:

+

Average of y-coordinates of points:

+ `, + }); + + let x1 = -3, + y1 = 1; + let x2 = -7, + y2 = 5; + let x3 = 4, + y3 = 2; + + let meany = (y1 + y2 + y1 + y3 + x2) / 5; + + let xs = [x1, x2, x1, x3, y2]; + let ys = [y1, y2, y1, y3, x2]; + let stateVariables = await returnAllStateVariables(core); + for (let i = 0; i < 5; i++) { + expect(stateVariables[`/q${i + 1}`].stateValues.xs[0].tree).eq( + xs[i], + ); + expect(stateVariables[`/q${i + 1}`].stateValues.xs[1].tree).eq( + ys[i], + ); + expect(stateVariables[`/qa${i + 1}`].stateValues.xs[0].tree).eq( + xs[i], + ); + expect(stateVariables[`/qa${i + 1}`].stateValues.xs[1].tree).eq( + ys[i], + ); + expect(stateVariables[`/c${i + 1}`].stateValues.value.tree).eqls([ + "vector", + xs[i], + ys[i], + ]); + expect(stateVariables[`/x${i + 1}`].stateValues.value.tree).eq( + xs[i], + ); + expect(stateVariables[`/xc${i + 1}`].stateValues.value.tree).eq( + xs[i], + ); + expect(stateVariables[`/xe${i + 1}`].stateValues.value.tree).eq( + xs[i], + ); + expect(stateVariables[`/y${i + 1}`].stateValues.value.tree).eq( + ys[i], + ); + } + expect(stateVariables["/mean"].stateValues.value.tree).eq(meany); + }); + + it("collect from source that initially does not exist", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + (1,2) + (3,4) + + + + + `, + }); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/bi", + core, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/P1"].stateValues.xs.map((x) => x.tree)).eqls([ + 1, 2, + ]); + expect(stateVariables["/P2"].stateValues.xs.map((x) => x.tree)).eqls([ + 3, 4, + ]); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/copy.test.ts b/packages/doenetml-worker/src/test/tagSpecific/copy.test.ts new file mode 100644 index 000000000..8bc6da005 --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/copy.test.ts @@ -0,0 +1,8654 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { cleanLatex } from "../utils/math"; +import { + updateBooleanInputValue, + updateMathInputImmediateValue, + updateMathInputValue, + updateMathInputValueToImmediateValue, + updateTextInputValue, +} from "../utils/actions"; +import me from "math-expressions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +function isUndefinedOrInactive(comp) { + expect( + comp === undefined || comp.stateValues.isInactiveCompositeReplacement, + ).eq(true); +} + +describe("Copy tag tests", async () => { + it("copy copies properties, macros", async () => { + let core = await createTestCore({ + doenetML: ` + x + $math1{name="a"} + $a{name="b"} + x + $math2{name="c"} + $c{name="d"} + (1,2) + $point1{name="e"} + $e{name="f"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/math1"].stateValues.modifyIndirectly).eq(false); + expect(stateVariables["/a"].stateValues.modifyIndirectly).eq(false); + expect(stateVariables["/b"].stateValues.modifyIndirectly).eq(false); + expect(stateVariables["/math2"].stateValues.modifyIndirectly).eq(true); + expect(stateVariables["/c"].stateValues.modifyIndirectly).eq(true); + expect(stateVariables["/d"].stateValues.modifyIndirectly).eq(true); + expect(stateVariables["/point1"].stateValues.label).eq("A"); + expect(stateVariables["/e"].stateValues.label).eq("A"); + expect(stateVariables["/f"].stateValues.label).eq("A"); + }); + + it("copy copies properties, with copySource", async () => { + let core = await createTestCore({ + doenetML: ` + x + x + + + + + (1,2) + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/math1"].stateValues.modifyIndirectly).eq(false); + expect(stateVariables["/a"].stateValues.modifyIndirectly).eq(false); + expect(stateVariables["/b"].stateValues.modifyIndirectly).eq(false); + expect(stateVariables["/math2"].stateValues.modifyIndirectly).eq(true); + expect(stateVariables["/c"].stateValues.modifyIndirectly).eq(true); + expect(stateVariables["/d"].stateValues.modifyIndirectly).eq(true); + expect(stateVariables["/point1"].stateValues.label).eq("A"); + expect(stateVariables["/e"].stateValues.label).eq("A"); + expect(stateVariables["/f"].stateValues.label).eq("A"); + }); + + it("copy overwrites properties, macros", async () => { + let core = await createTestCore({ + doenetML: ` + x + $math1{name="r1" } + $math1{name="r2" modifyIndirectly="true" } + $r1{name="r3" modifyIndirectly="true" } + $r2{name="r4" } + $r3{name="r5" } + $r2{name="r6" modifyIndirectly="false" } + $r3{name="r7" modifyIndirectly="false" } + (1,2) + $A{name="A2" } + $A{name="B" labelIsName } + $A2{name="B2" } + $B{name="C" labelIsName } + $B{name="C2" } + $C{name="D" labelIsName } + $C{name="D2" } + $C2{name="D5" labelIsName } + $C2{name="D6" } + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/math1"].stateValues.modifyIndirectly).eq(false); + expect(stateVariables["/r1"].stateValues.modifyIndirectly).eq(false); + expect(stateVariables["/r2"].stateValues.modifyIndirectly).eq(true); + expect(stateVariables["/r3"].stateValues.modifyIndirectly).eq(true); + expect(stateVariables["/r4"].stateValues.modifyIndirectly).eq(true); + expect(stateVariables["/r5"].stateValues.modifyIndirectly).eq(true); + expect(stateVariables["/r6"].stateValues.modifyIndirectly).eq(false); + expect(stateVariables["/r7"].stateValues.modifyIndirectly).eq(false); + + expect(stateVariables["/A"].stateValues.label).eq("A"); + expect(stateVariables["/A2"].stateValues.label).eq("A"); + expect(stateVariables["/B"].stateValues.label).eq("B"); + expect(stateVariables["/B2"].stateValues.label).eq("A"); + expect(stateVariables["/C"].stateValues.label).eq("C"); + expect(stateVariables["/C2"].stateValues.label).eq("B"); + expect(stateVariables["/D"].stateValues.label).eq("D"); + expect(stateVariables["/D2"].stateValues.label).eq("C"); + expect(stateVariables["/D5"].stateValues.label).eq("D5"); + expect(stateVariables["/D6"].stateValues.label).eq("B"); + }); + + it("copy overwrites properties, with copySource", async () => { + let core = await createTestCore({ + doenetML: ` + x + + + + + + + + + (1,2) + (1,2) + + + + + + + + + + + + + + + + + + + + + + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/math1"].stateValues.modifyIndirectly).eq(false); + expect(stateVariables["/r1"].stateValues.modifyIndirectly).eq(false); + expect(stateVariables["/r2"].stateValues.modifyIndirectly).eq(true); + expect(stateVariables["/r3"].stateValues.modifyIndirectly).eq(true); + expect(stateVariables["/r4"].stateValues.modifyIndirectly).eq(true); + expect(stateVariables["/r5"].stateValues.modifyIndirectly).eq(true); + expect(stateVariables["/r6"].stateValues.modifyIndirectly).eq(false); + expect(stateVariables["/r7"].stateValues.modifyIndirectly).eq(false); + + expect(stateVariables["/A"].stateValues.label).eq("A"); + expect(stateVariables["/A2"].stateValues.label).eq("A"); + expect(stateVariables["/A3"].stateValues.label).eq("A"); + expect(stateVariables["/A4"].stateValues.label).eq("A"); + expect(stateVariables["/B"].stateValues.label).eq("B"); + expect(stateVariables["/B2"].stateValues.label).eq("A"); + expect(stateVariables["/B3"].stateValues.label).eq("B"); + expect(stateVariables["/B4"].stateValues.label).eq("B4"); + expect(stateVariables["/B5"].stateValues.label).eq("A"); + expect(stateVariables["/B6"].stateValues.label).eq("B"); + expect(stateVariables["/C"].stateValues.label).eq("C"); + expect(stateVariables["/C2"].stateValues.label).eq("B"); + expect(stateVariables["/C3"].stateValues.label).eq("C"); + expect(stateVariables["/C4"].stateValues.label).eq("C4"); + expect(stateVariables["/C5"].stateValues.label).eq("A"); + expect(stateVariables["/C6"].stateValues.label).eq("C"); + expect(stateVariables["/C7"].stateValues.label).eq("C7"); + expect(stateVariables["/C8"].stateValues.label).eq("B"); + expect(stateVariables["/C9"].stateValues.label).eq("C"); + expect(stateVariables["/C10"].stateValues.label).eq("C10"); + expect(stateVariables["/C11"].stateValues.label).eq("B4"); + expect(stateVariables["/C12"].stateValues.label).eq("C"); + expect(stateVariables["/C13"].stateValues.label).eq("C13"); + expect(stateVariables["/C14"].stateValues.label).eq("A"); + expect(stateVariables["/C15"].stateValues.label).eq("C"); + expect(stateVariables["/C16"].stateValues.label).eq("C16"); + expect(stateVariables["/C17"].stateValues.label).eq("B"); + expect(stateVariables["/C18"].stateValues.label).eq("C"); + }); + + it("copy overwrites properties, decode XML entities, macros", async () => { + let core = await createTestCore({ + doenetML: ` + x + $math1{name="r1" } + $math1{name="r2" modifyIndirectly="3<4" } + $r1{name="r3" modifyIndirectly="3<4" } + $r2{name="r4" } + $r3{name="r5" } + $r2{name="r6" modifyIndirectly="3>4" } + $r3{name="r7" modifyIndirectly="3>4" } + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/math1"].stateValues.modifyIndirectly).eq(false); + expect(stateVariables["/r1"].stateValues.modifyIndirectly).eq(false); + expect(stateVariables["/r2"].stateValues.modifyIndirectly).eq(true); + expect(stateVariables["/r3"].stateValues.modifyIndirectly).eq(true); + expect(stateVariables["/r4"].stateValues.modifyIndirectly).eq(true); + expect(stateVariables["/r5"].stateValues.modifyIndirectly).eq(true); + expect(stateVariables["/r6"].stateValues.modifyIndirectly).eq(false); + expect(stateVariables["/r7"].stateValues.modifyIndirectly).eq(false); + }); + + it("copy overwrites properties, decode XML entities, with copySource", async () => { + let core = await createTestCore({ + doenetML: ` + x + + + + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/math1"].stateValues.modifyIndirectly).eq(false); + expect(stateVariables["/r1"].stateValues.modifyIndirectly).eq(false); + expect(stateVariables["/r2"].stateValues.modifyIndirectly).eq(true); + expect(stateVariables["/r3"].stateValues.modifyIndirectly).eq(true); + expect(stateVariables["/r4"].stateValues.modifyIndirectly).eq(true); + expect(stateVariables["/r5"].stateValues.modifyIndirectly).eq(true); + expect(stateVariables["/r6"].stateValues.modifyIndirectly).eq(false); + expect(stateVariables["/r7"].stateValues.modifyIndirectly).eq(false); + }); + + async function check_copy_props(core) { + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/x"].stateValues.modifyIndirectly).eq(false); + expect(stateVariables["/x"].stateValues.hidden).eq(true); + // modifyIndirectly attribute is copied (as it has propagateToProps=true) + expect(stateVariables["/mr"].stateValues.modifyIndirectly).eq(false); + // hide attribute is not copied (default behavior) + expect(stateVariables["/mr"].stateValues.hidden).eq(false); + expect(stateVariables["/mr"].stateValues.value).eq(false); + + // modifyIndirectly is overwritten + expect(stateVariables["/mr2"].stateValues.modifyIndirectly).eq(true); + expect(stateVariables["/mr2"].stateValues.hidden).eq(false); + expect(stateVariables["/mr2"].stateValues.value).eq(false); + + // modifyIndirectly attribute is copied (as it has propagateToProps=true) + expect(stateVariables["/frmt"].stateValues.modifyIndirectly).eq(false); + // hide attribute is not copied (default behavior) + expect(stateVariables["/frmt"].stateValues.hidden).eq(false); + expect(stateVariables["/frmt"].stateValues.value).eq("text"); + + expect(stateVariables["/frmt2"].stateValues.modifyIndirectly).eq(false); + expect(stateVariables["/frmt2"].stateValues.hidden).eq(true); + expect(stateVariables["/frmt2"].stateValues.value).eq("text"); + + // all attributes copied when don't use prop + expect(stateVariables["/frmt3"].stateValues.modifyIndirectly).eq(false); + expect(stateVariables["/frmt3"].stateValues.value).eq("text"); + expect(stateVariables["/frmt3"].stateValues.hidden).eq(true); + + expect(stateVariables["/A"].stateValues.label).eq("A"); + expect(stateVariables["/cA"].stateValues.value.tree).eqls([ + "vector", + 1, + 2, + ]); + expect(stateVariables["/l"].stateValues.value).eq( + "\\left( 1, 2 \\right)", + ); + expect(stateVariables["/l"].stateValues.modifyIndirectly).eq(true); + expect(stateVariables["/lmr"].stateValues.value).eq( + "\\left( 1, 2 \\right)", + ); + expect(stateVariables["/lmr"].stateValues.modifyIndirectly).eq(false); + expect(stateVariables["/A2"].stateValues.label).eq("A"); + expect(stateVariables["/cA2"].stateValues.value.tree).eqls([ + "vector", + 1, + 2, + ]); + expect(stateVariables["/l2"].stateValues.value).eq( + "\\left( 1, 2 \\right)", + ); + } + + it("copy props, dot notation, macros", async () => { + let core = await createTestCore({ + doenetML: ` + x + $(x.modifyIndirectly{assignNames="mr" }) + $(x.modifyIndirectly{assignNames="mr2" modifyIndirectly="true" }) + + $(x.format{assignNames="frmt" }) + $(x.format{assignNames="frmt2" hide }) + $frmt{name="frmt3" hide } + + (1,2) + $(A.coords{assignNames="cA" }) + $(cA.latex{assignNames="l" }) + $(cA.latex{assignNames="lmr" modifyIndirectly="false" }) + $A{name="A2" } + $(A2.coords{assignNames="cA2" }) + $(cA2.latex{assignNames="l2" }) + `, + }); + + await check_copy_props(core); + }); + + it("copy props, with copySource, dot notation", async () => { + let core = await createTestCore({ + doenetML: ` + x + + + + + + + + (1,2) + + + + + + + `, + }); + + await check_copy_props(core); + }); + + async function test_copy_prop_updatable(core) { + async function check_items(x, y) { + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.xs[0].tree).eq(x); + expect(stateVariables["/p1"].stateValues.xs[1].tree).eq(y); + expect(stateVariables["/p2"].stateValues.xs[0].tree).eq(x); + expect(stateVariables["/p2"].stateValues.xs[1].tree).eq(y); + expect(stateVariables["/p3"].stateValues.xs[0].tree).eq(y); + expect(stateVariables["/p3"].stateValues.xs[1].tree).eq(x); + } + + let x = 1, + y = 2; + + // initial position + await check_items(x, y); + + // move point 1 + x = -3; + y = 5; + await core.requestAction({ + actionName: "movePoint", + componentName: "/p1", + args: { x, y }, + event: null, + }); + await check_items(x, y); + + // move point 2 + x = 6; + y = -9; + await core.requestAction({ + actionName: "movePoint", + componentName: "/p2", + args: { x, y }, + event: null, + }); + await check_items(x, y); + + // move point 3 + x = -7; + y = -2; + await core.requestAction({ + actionName: "movePoint", + componentName: "/p3", + args: { x: y, y: x }, + event: null, + }); + await check_items(x, y); + } + + it("copy props of copy still updatable, dot notation, macros", async () => { + let core = await createTestCore({ + doenetML: ` + + (1,2) + + + + $p1{name="p2"} + + ($p2.y, $p2.x1) + + + $p1{name="p1a"} + $p2{name="p2a"} + $p3{name="p3a"} + `, + }); + + await test_copy_prop_updatable(core); + }); + + it("copy props of copy still updatable, with copySource, dot notation", async () => { + let core = await createTestCore({ + doenetML: ` + + (1,2) + + + + + + (, + ) + + + + + + `, + }); + + await test_copy_prop_updatable(core); + }); + + async function test_copy_prop_shadows_source(core) { + // initial positions + let displacement = [-4, 2]; + let v_tail = [1, 1]; + let d_tail = [0, 0]; + let v_head = displacement.map((x, i) => x + v_tail[i]); + let d_head = displacement.map((x, i) => x + d_tail[i]); + + let stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/vector1"].stateValues.tail.map((x) => x.tree), + ).eqls(v_tail); + expect( + stateVariables["/vector1"].stateValues.head.map((x) => x.tree), + ).eqls(v_head); + expect( + stateVariables["/vector1"].stateValues.displacement.map( + (x) => x.tree, + ), + ).eqls(displacement); + expect(stateVariables["/d1"].stateValues.tail.map((x) => x.tree)).eqls( + d_tail, + ); + expect(stateVariables["/d1"].stateValues.head.map((x) => x.tree)).eqls( + d_head, + ); + expect( + stateVariables["/d1"].stateValues.displacement.map((x) => x.tree), + ).eqls(displacement); + expect(stateVariables["/d2"].stateValues.tail.map((x) => x.tree)).eqls( + d_tail, + ); + expect(stateVariables["/d2"].stateValues.head.map((x) => x.tree)).eqls( + d_head, + ); + expect( + stateVariables["/d2"].stateValues.displacement.map((x) => x.tree), + ).eqls(displacement); + + // move vector 1 + displacement = [3, 1]; + v_tail = [-1, 4]; + d_tail = [0, 0]; + v_head = displacement.map((x, i) => x + v_tail[i]); + d_head = displacement.map((x, i) => x + d_tail[i]); + + await core.requestAction({ + actionName: "moveVector", + componentName: "/vector1", + args: { + tailcoords: v_tail, + headcoords: v_head, + }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/vector1"].stateValues.tail.map((x) => x.tree), + ).eqls(v_tail); + expect( + stateVariables["/vector1"].stateValues.head.map((x) => x.tree), + ).eqls(v_head); + expect( + stateVariables["/vector1"].stateValues.displacement.map( + (x) => x.tree, + ), + ).eqls(displacement); + expect(stateVariables["/d1"].stateValues.tail.map((x) => x.tree)).eqls( + d_tail, + ); + expect(stateVariables["/d1"].stateValues.head.map((x) => x.tree)).eqls( + d_head, + ); + expect( + stateVariables["/d1"].stateValues.displacement.map((x) => x.tree), + ).eqls(displacement); + expect(stateVariables["/d2"].stateValues.tail.map((x) => x.tree)).eqls( + d_tail, + ); + expect(stateVariables["/d2"].stateValues.head.map((x) => x.tree)).eqls( + d_head, + ); + expect( + stateVariables["/d2"].stateValues.displacement.map((x) => x.tree), + ).eqls(displacement); + + // move vector 2 + displacement = [5, -2]; + v_tail = [-1, 4]; + d_tail = [3, -7]; + v_head = displacement.map((x, i) => x + v_tail[i]); + d_head = displacement.map((x, i) => x + d_tail[i]); + + await core.requestAction({ + actionName: "moveVector", + componentName: "/d1", + args: { + tailcoords: d_tail, + headcoords: d_head, + }, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/vector1"].stateValues.tail.map((x) => x.tree), + ).eqls(v_tail); + expect( + stateVariables["/vector1"].stateValues.head.map((x) => x.tree), + ).eqls(v_head); + expect( + stateVariables["/vector1"].stateValues.displacement.map( + (x) => x.tree, + ), + ).eqls(displacement); + expect(stateVariables["/d1"].stateValues.tail.map((x) => x.tree)).eqls( + d_tail, + ); + expect(stateVariables["/d1"].stateValues.head.map((x) => x.tree)).eqls( + d_head, + ); + expect( + stateVariables["/d1"].stateValues.displacement.map((x) => x.tree), + ).eqls(displacement); + expect(stateVariables["/d2"].stateValues.tail.map((x) => x.tree)).eqls( + d_tail, + ); + expect(stateVariables["/d2"].stateValues.head.map((x) => x.tree)).eqls( + d_head, + ); + expect( + stateVariables["/d2"].stateValues.displacement.map((x) => x.tree), + ).eqls(displacement); + + // move vector 3 + displacement = [-3, 6]; + v_tail = [-1, 4]; + d_tail = [4, -2]; + v_head = displacement.map((x, i) => x + v_tail[i]); + d_head = displacement.map((x, i) => x + d_tail[i]); + + await core.requestAction({ + actionName: "moveVector", + componentName: "/d2", + args: { + tailcoords: d_tail, + headcoords: d_head, + }, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/vector1"].stateValues.tail.map((x) => x.tree), + ).eqls(v_tail); + expect( + stateVariables["/vector1"].stateValues.head.map((x) => x.tree), + ).eqls(v_head); + expect( + stateVariables["/vector1"].stateValues.displacement.map( + (x) => x.tree, + ), + ).eqls(displacement); + expect(stateVariables["/d1"].stateValues.tail.map((x) => x.tree)).eqls( + d_tail, + ); + expect(stateVariables["/d1"].stateValues.head.map((x) => x.tree)).eqls( + d_head, + ); + expect( + stateVariables["/d1"].stateValues.displacement.map((x) => x.tree), + ).eqls(displacement); + expect(stateVariables["/d2"].stateValues.tail.map((x) => x.tree)).eqls( + d_tail, + ); + expect(stateVariables["/d2"].stateValues.head.map((x) => x.tree)).eqls( + d_head, + ); + expect( + stateVariables["/d2"].stateValues.displacement.map((x) => x.tree), + ).eqls(displacement); + + // move vector 1 + displacement = [5, 0]; + v_tail = [-8, 6]; + d_tail = [4, -2]; + v_head = displacement.map((x, i) => x + v_tail[i]); + d_head = displacement.map((x, i) => x + d_tail[i]); + + await core.requestAction({ + actionName: "moveVector", + componentName: "/vector1", + args: { + tailcoords: v_tail, + headcoords: v_head, + }, + }); + + stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/vector1"].stateValues.tail.map((x) => x.tree), + ).eqls(v_tail); + expect( + stateVariables["/vector1"].stateValues.head.map((x) => x.tree), + ).eqls(v_head); + expect( + stateVariables["/vector1"].stateValues.displacement.map( + (x) => x.tree, + ), + ).eqls(displacement); + expect(stateVariables["/d1"].stateValues.tail.map((x) => x.tree)).eqls( + d_tail, + ); + expect(stateVariables["/d1"].stateValues.head.map((x) => x.tree)).eqls( + d_head, + ); + expect( + stateVariables["/d1"].stateValues.displacement.map((x) => x.tree), + ).eqls(displacement); + expect(stateVariables["/d2"].stateValues.tail.map((x) => x.tree)).eqls( + d_tail, + ); + expect(stateVariables["/d2"].stateValues.head.map((x) => x.tree)).eqls( + d_head, + ); + expect( + stateVariables["/d2"].stateValues.displacement.map((x) => x.tree), + ).eqls(displacement); + } + + it("copy of prop copy shadows source, dot notation, macros", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + $(vector1.displacement{assignNames="d1"}) + + + + $d1{name="d2"} + + + $vector1{name="v1a"} + `, + }); + + await test_copy_prop_shadows_source(core); + }); + + it("copy of prop copy shadows source, with copySource, dot notation", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + + + + + + `, + }); + + await test_copy_prop_shadows_source(core); + }); + + async function test_property_children_replacement_changes(core) { + async function check_items(list: string) { + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p1"].stateValues.text.trim()).eq(list); + expect(stateVariables["/p2"].stateValues.text.trim()).eq(list); + expect(stateVariables["/p3"].stateValues.text.trim()).eq(list); + expect(stateVariables["/p4"].stateValues.text.trim()).eq(list); + expect(stateVariables["/p5"].stateValues.text.trim()).eq(list); + } + + await check_items(""); + + await updateMathInputValue({ latex: "2", componentName: "/mi", core }); + await check_items("a, b"); + + await updateMathInputValue({ latex: "5", componentName: "/mi", core }); + await check_items("a, b, c, d, e"); + + await updateMathInputValue({ latex: "1", componentName: "/mi", core }); + await check_items("a"); + + await updateMathInputValue({ latex: "6", componentName: "/mi", core }); + await check_items("a, b, c, d, e, f"); + } + + it("property children account for replacement changes, macros", async () => { + let core = await createTestCore({ + doenetML: ` + + +

+ + + +

+ +

$al1{name="al2"}

+ $p1{name="p3"} + +

$al2

+ $p3{name="p5"} + + `, + }); + + await test_property_children_replacement_changes(core); + }); + + it("property children account for replacement changes, with copySource", async () => { + let core = await createTestCore({ + doenetML: ` + + +

+ + + +

+ +

+ +

+ +

+ +

+ + `, + }); + + await test_property_children_replacement_changes(core); + }); + + it("copy macros", async () => { + let core = await createTestCore({ + doenetML: ` +

a=

+

b=

+

c=

+ +

ax^2+bx+c = $a x^2 + $b x + $c

+

ax^2+bx+c = $s

+

ax^2+bx+c = $$s

+

ax^2+bx+c = $$$s

+

$orig{name="singlem"}

+

$$orig

+

$$$orig

+ + `, + }); + + async function check_items(a, b, c) { + let stateVariables = await returnAllStateVariables(core); + let polyLatex = `${a}x^{2}+${b}x+${c}`; + + expect(cleanLatex(stateVariables["/orig"].stateValues.latex)).eq( + `ax^2+bx+c=${polyLatex}`, + ); + expect(cleanLatex(stateVariables["/single"].stateValues.latex)).eq( + `ax^2+bx+c=${polyLatex}`, + ); + expect(cleanLatex(stateVariables["/double"].stateValues.latex)).eq( + `ax^2+bx+c=$$s`, + ); + expect(cleanLatex(stateVariables["/triple"].stateValues.latex)).eq( + `ax^2+bx+c=$$$s`, + ); + expect(cleanLatex(stateVariables["/singlem"].stateValues.latex)).eq( + `ax^2+bx+c=${polyLatex}`, + ); + expect(stateVariables["/doublem"].stateValues.text).eq(`$$orig`); + expect(stateVariables["/triplem"].stateValues.text).eq(`$$$orig`); + } + + await check_items(5, 2, 3); + + // Enter new numbers + await updateMathInputValue({ latex: "9", componentName: "/a", core }); + await updateMathInputValue({ latex: "6", componentName: "/b", core }); + await updateMathInputValue({ latex: "7", componentName: "/c", core }); + await check_items(9, 6, 7); + }); + + it("macros after failed double macro", async () => { + let core = await createTestCore({ + doenetML: ` + hi + bye +

$t, $$t, $ $u, + $t, $$u, $u

+

$u, $$t(, $t, + $u, $$u, $t

+

$t, $$$t, $5, $u, $$5, $t, $$$5, $u

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq( + "hi, $$t, $ bye,\n hi, $$u, bye", + ); + expect(stateVariables["/p2"].stateValues.text).eq( + "bye, $$t(, hi,\n bye, $$u, hi", + ); + expect(stateVariables["/p3"].stateValues.text).eq( + "hi, $$$t, $5, bye, $$5, hi, $$$5, bye", + ); + }); + + async function test_copy_not_ignore_hide(core) { + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq("Hidden text: "); + expect(stateVariables["/p2"].stateValues.text).eq( + "Hidden by default: ", + ); + expect(stateVariables["/p3"].stateValues.text).eq( + "Force to reveal: secret", + ); + expect(stateVariables["/p4"].stateValues.text).eq( + "Force to reveal 2: secret", + ); + } + + it("copy does not ignore hide by default, macros", async () => { + let core = await createTestCore({ + doenetML: ` +

Hidden text: secret

+

Hidden by default: $hidden

+

Force to reveal: $hidden{hide="false"}

+

Force to reveal 2: $hidden{sourceAttributesToIgnore="hide"}

+ + `, + }); + + await test_copy_not_ignore_hide(core); + }); + + it("copy does not ignore hide by default, with copySource", async () => { + let core = await createTestCore({ + doenetML: ` +

Hidden text: secret

+

Hidden by default:

+

Force to reveal:

+

Force to reveal 2:

+ + `, + }); + + await test_copy_not_ignore_hide(core); + }); + + async function test_copy_hidden_children(core) { + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theP"].stateValues.text).eq("Hidden text: "); + expect(stateVariables["/pHidden"].stateValues.text).eq("Hidden: "); + expect(stateVariables["/pReveal"].stateValues.text).eq( + "Revealed: secret", + ); + expect(stateVariables["/theP2"].stateValues.text).eq("Hidden text: "); + expect(stateVariables["/pHidden2"].stateValues.text).eq("Hidden 2: "); + expect(stateVariables["/pReveal2"].stateValues.text).eq( + "Revealed 2: secret", + ); + expect(stateVariables["/theP3"].stateValues.text).eq( + "Hidden text: secret", + ); + expect(stateVariables["/pReveal3"].stateValues.text).eq( + "Revealed 3: secret", + ); + expect(stateVariables["/theP4"].stateValues.text).eq("Hidden text: "); + expect(stateVariables["/pHidden4"].stateValues.text).eq("Hidden 4: "); + expect(stateVariables["/pReveal4"].stateValues.text).eq( + "Revealed 4: secret", + ); + } + + it("copy keeps hidden children hidden, all macros", async () => { + let core = await createTestCore({ + doenetML: ` +

Hidden text: secret

+

Hidden: $(theP/hidden)

+

Revealed: $(theP/hidden{hide="false"})

+ $theP{name="theP2"} +

Hidden 2: $(theP2/hidden)

+

Revealed 2: $(theP2/hidden{hide="false"})

+ $theP{sourceAttributesToIgnore="hide" name="theP3"} +

Revealed 3: $(theP3/hidden)

+ $theP{hide="false" name="theP4"} +

Hidden 4: $(theP4/hidden)

+

Revealed 4: $(theP4/hidden{hide="false"})

+ + `, + }); + + await test_copy_hidden_children(core); + }); + + it("copy keeps hidden children hidden, with copySource", async () => { + let core = await createTestCore({ + doenetML: ` +

Hidden text: secret

+

Hidden:

+

Revealed:

+

+

Hidden 2:

+

Revealed 2:

+

+

Revealed 3:

+

+

Hidden 4:

+

Revealed 4:

+ + `, + }); + + await test_copy_hidden_children(core); + }); + + async function test_copy_hides_dynamically(core) { + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/c1"].stateValues.text).eq("copy 1: hello"); + expect(stateVariables["/c2"].stateValues.text).eq("copy 2: "); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/h1", + core, + }); + await updateBooleanInputValue({ + boolean: false, + componentName: "/h2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/c1"].stateValues.text).eq("copy 1: "); + expect(stateVariables["/c2"].stateValues.text).eq("copy 2: hello"); + + await updateBooleanInputValue({ + boolean: false, + componentName: "/h1", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/h2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/c1"].stateValues.text).eq("copy 1: hello"); + expect(stateVariables["/c2"].stateValues.text).eq("copy 2: "); + } + + it("copies hide dynamically, macros", async () => { + let core = await createTestCore({ + doenetML: ` + hello + + + + + + + + +

copy 1: $source{hide="$h1"}

+

copy 2: $source{hide="$h2"}

+ `, + }); + + await test_copy_hides_dynamically(core); + }); + + it("copies hide dynamically, with copySource", async () => { + let core = await createTestCore({ + doenetML: ` + hello + + + + + + + + +

copy 1:

+

copy 2:

+ `, + }); + + await test_copy_hides_dynamically(core); + }); + + async function test_copy_change_away_copy(core) { + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/forVerb"].stateValues.text).eq("jump"); + expect(stateVariables["/verb2"].stateValues.text).eq("jump"); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/b", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/forVerb"].stateValues.text).eq("skip"); + expect(stateVariables["/verb2"].stateValues.text).eq("skip"); + + await updateBooleanInputValue({ + boolean: false, + componentName: "/b", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/forVerb"].stateValues.text).eq("jump"); + expect(stateVariables["/verb2"].stateValues.text).eq("jump"); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/b", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/forVerb"].stateValues.text).eq("skip"); + expect(stateVariables["/verb2"].stateValues.text).eq("skip"); + } + + it("copy of component that changes away from a copy, macros", async () => { + let core = await createTestCore({ + doenetML: ` + + + + jump + + +

+ skip + $jump +

+ + $verb{name="verb2"} + `, + }); + + await test_copy_change_away_copy(core); + }); + + it("copy of component that changes away from a copy, with copySource", async () => { + let core = await createTestCore({ + doenetML: ` + + + + jump + + +

+ skip + $jump +

+ + + `, + }); + + await test_copy_change_away_copy(core); + }); + + it("copy of invalid source gives math in boolean and math", async () => { + let core = await createTestCore({ + doenetML: ` +

We can't see $invalid in paragraph or $invisible in text.

+ +

In math, we can: $bad + $nothing

+ +

And in boolean as well: not ($missing = x)

. + +`, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq( + "We can't see in paragraph or in text.", + ); + expect(stateVariables["/m1"].stateValues.value.tree).eqls([ + "+", + "_", + "_", + ]); + expect(stateVariables["/b1"].stateValues.value).eq(true); + }); + + it("copy no link, base test, with copySource", async () => { + let core = await createTestCore({ + doenetML: ` +

Simplify of original:

+

Simplify of copies:

+ +

Original: x +x

+ +

Unlinked copy:

+ +

Linked copy:

+ +

Double value of original: + +

+

Double value of copy 1: + +

+

Double value of copy 2: + +

+ + `, + }); + + async function check_maths(m, m2, m3) { + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/m"].stateValues.value.tree).eqls(m); + expect(stateVariables["/m2"].stateValues.value.tree).eqls(m2); + expect(stateVariables["/m3"].stateValues.value.tree).eqls(m3); + } + + let stateVariables = await returnAllStateVariables(core); + let copy1Name = stateVariables["/m2"].replacementOf; + let copy2Name = stateVariables["/m3"].replacementOf; + expect(stateVariables[copy1Name].stateValues.link).eq(false); + expect(stateVariables[copy2Name].stateValues.link).eq(true); + + await check_maths(["*", 2, "x"], ["+", "x", "x"], ["+", "x", "x"]); + + // simplify copies + await updateTextInputValue({ + text: "full", + componentName: "/s2", + core, + }); + await check_maths(["*", 2, "x"], ["*", 2, "x"], ["*", 2, "x"]); + + // stop simplifying original + await updateTextInputValue({ + text: "none", + componentName: "/s1", + core, + }); + await check_maths(["+", "x", "x"], ["*", 2, "x"], ["*", 2, "x"]); + + // double original + await core.requestAction({ + componentName: "/doubleOriginal", + actionName: "updateValue", + args: {}, + event: null, + }); + await check_maths( + ["*", 2, ["+", "x", "x"]], + ["*", 2, "x"], + ["*", 4, "x"], + ); + + // double copy1 + await core.requestAction({ + componentName: "/doubleCopy1", + actionName: "updateValue", + args: {}, + event: null, + }); + await check_maths( + ["*", 2, ["+", "x", "x"]], + ["*", 4, "x"], + ["*", 4, "x"], + ); + + // double copy2 + await core.requestAction({ + componentName: "/doubleCopy2", + actionName: "updateValue", + args: {}, + event: null, + }); + await check_maths(["*", 2, 4, "x"], ["*", 4, "x"], ["*", 8, "x"]); + + // stop simplifying copies + await updateTextInputValue({ + text: "none", + componentName: "/s2", + core, + }); + await check_maths(["*", 2, 4, "x"], ["*", 2, 2, "x"], ["*", 2, 4, "x"]); + }); + + async function test_copy_points_lines_no_link(core) { + async function check_items({ + A, + B, + A2, + l2A, + l2B, + A3, + A4, + B4, + gA, + gB, + Ax, + }) { + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/A"].stateValues.xs.map((x) => x.tree)).eqls( + A, + ); + expect(stateVariables["/B"].stateValues.xs.map((x) => x.tree)).eqls( + B, + ); + expect( + stateVariables["/l"].stateValues.point1.map((x) => x.tree), + ).eqls(A); + expect( + stateVariables["/l"].stateValues.point2.map((x) => x.tree), + ).eqls(B); + expect( + stateVariables["/A2"].stateValues.xs.map((x) => x.tree), + ).eqls(A2); + expect( + stateVariables["/l2"].stateValues.point1.map((x) => x.tree), + ).eqls(l2A); + expect( + stateVariables["/l2"].stateValues.point2.map((x) => x.tree), + ).eqls(l2B); + expect( + stateVariables["/A3"].stateValues.xs.map((x) => x.tree), + ).eqls(A3); + expect( + stateVariables["/A4"].stateValues.xs.map((x) => x.tree), + ).eqls(A4); + expect( + stateVariables["/B4"].stateValues.xs.map((x) => x.tree), + ).eqls(B4); + expect( + stateVariables["/gnolink/A"].stateValues.xs.map((x) => x.tree), + ).eqls(gA); + expect( + stateVariables["/gnolink/B"].stateValues.xs.map((x) => x.tree), + ).eqls(gB); + expect( + stateVariables["/gnolink/l"].stateValues.point1.map( + (x) => x.tree, + ), + ).eqls(gA); + expect( + stateVariables["/gnolink/l"].stateValues.point2.map( + (x) => x.tree, + ), + ).eqls(gB); + expect(stateVariables["/Ax"].stateValues.value.tree).eqls(Ax); + } + + let A = [1, 2], + B = [3, 4], + A2 = [1, 2], + l2A = [1, 2], + l2B = [3, 4], + A3 = [1, 2], + A4 = [1, 2], + B4 = [3, 4], + gA = [1, 2], + gB = [3, 4], + Ax = 1; + + let stateVariables = await returnAllStateVariables(core); + + let copyForA2 = stateVariables["/A2"].replacementOf; + let copyForl2 = stateVariables["/l2"].replacementOf; + let copyForA3 = stateVariables["/A3"].replacementOf; + let copyForA4B4 = stateVariables["/A4"].replacementOf; + let copyForgnolink = stateVariables["/gnolink"].replacementOf; + let copyForAx = stateVariables["/Ax"].replacementOf; + expect(stateVariables[copyForA2].stateValues.link).eq(false); + expect(stateVariables[copyForl2].stateValues.link).eq(false); + expect(stateVariables[copyForA3].stateValues.link).eq(false); + expect(stateVariables[copyForA4B4].stateValues.link).eq(false); + expect(stateVariables[copyForgnolink].stateValues.link).eq(false); + expect(stateVariables[copyForAx].stateValues.link).eq(false); + + await check_items({ A, B, A2, l2A, l2B, A3, A4, B4, gA, gB, Ax }); + + // move A + A = [-9, -3]; + await core.requestAction({ + actionName: "movePoint", + componentName: "/A", + args: { x: A[0], y: A[1] }, + event: null, + }); + await check_items({ A, B, A2, l2A, l2B, A3, A4, B4, gA, gB, Ax }); + + // move B + B = [-2, 6]; + await core.requestAction({ + actionName: "movePoint", + componentName: "/B", + args: { x: B[0], y: B[1] }, + event: null, + }); + await check_items({ A, B, A2, l2A, l2B, A3, A4, B4, gA, gB, Ax }); + + // move l + A = [-7, -6]; + B = [8, 0]; + + await core.requestAction({ + actionName: "moveLine", + componentName: "/l", + args: { + point1coords: A, + point2coords: B, + }, + }); + await check_items({ A, B, A2, l2A, l2B, A3, A4, B4, gA, gB, Ax }); + + // move A2 + A2 = [5, 4]; + core.requestAction({ + actionName: "movePoint", + componentName: "/A2", + args: { x: A2[0], y: A2[1] }, + event: null, + }); + await check_items({ A, B, A2, l2A, l2B, A3, A4, B4, gA, gB, Ax }); + + // move l2 + l2A = [-5, 9]; + l2B = [-4, -1]; + await core.requestAction({ + actionName: "moveLine", + componentName: "/l2", + args: { + point1coords: l2A, + point2coords: l2B, + }, + }); + await check_items({ A, B, A2, l2A, l2B, A3, A4, B4, gA, gB, Ax }); + + // move A3 + A3 = [6, -3]; + await core.requestAction({ + actionName: "movePoint", + componentName: "/A3", + args: { x: A3[0], y: A3[1] }, + event: null, + }); + await check_items({ A, B, A2, l2A, l2B, A3, A4, B4, gA, gB, Ax }); + + // move A4 + A4 = [-2, 7]; + await core.requestAction({ + actionName: "movePoint", + componentName: "/A4", + args: { x: A4[0], y: A4[1] }, + event: null, + }); + await check_items({ A, B, A2, l2A, l2B, A3, A4, B4, gA, gB, Ax }); + + // move B4 + B4 = [-9, -8]; + await core.requestAction({ + actionName: "movePoint", + componentName: "/B4", + args: { x: B4[0], y: B4[1] }, + event: null, + }); + await check_items({ A, B, A2, l2A, l2B, A3, A4, B4, gA, gB, Ax }); + + // move A5 + gA = [-10, -9]; + await core.requestAction({ + actionName: "movePoint", + componentName: "/gnolink/A", + args: { x: gA[0], y: gA[1] }, + event: null, + }); + await check_items({ A, B, A2, l2A, l2B, A3, A4, B4, gA, gB, Ax }); + + // move B5 + gB = [-8, -7]; + await core.requestAction({ + actionName: "movePoint", + componentName: "/gnolink/B", + args: { x: gB[0], y: gB[1] }, + event: null, + }); + await check_items({ A, B, A2, l2A, l2B, A3, A4, B4, gA, gB, Ax }); + + // move l3 + gA = [6, 5]; + gB = [4, -3]; + await core.requestAction({ + actionName: "moveLine", + componentName: "/gnolink/l", + args: { + point1coords: gA, + point2coords: gB, + }, + event: null, + }); + await check_items({ A, B, A2, l2A, l2B, A3, A4, B4, gA, gB, Ax }); + } + + it("copy points and lines with no link, dot notation, macros", async () => { + let core = await createTestCore({ + doenetML: ` + + (1,2) + (3,4) + + + + + $A{link="false" name="A2"} + $l{link="false" name="l2"} + + + + $(l.point1{link="false" assignNames="A3"}) + + + $(l.points{link="false" assignNames="A4 B4" }) + + + $g{link="false" name="gnolink" newNamespace} + + $(A.x{link="false" assignNames="Ax" }) + +

+ $A{name="Ac"} + $B{name="Bc"} + $(l.point1{assignNames="lp1"}) + $A2{name="A2c"} + $(l2.point1{assignNames="l2p1"}) + $A3{name="A3c"} + $A4{name="A4c"} + $B4{name="B4c"} + $(gnolink/A{name="A5c"}) + $(gnolink/B{name="B5c"}) + $(gnolink/l.point1{assignNames="l3p1"}) + +

+ + `, + }); + + await test_copy_points_lines_no_link(core); + }); + + it("copy points and lines with no link, with copySource, dot notation", async () => { + let core = await createTestCore({ + doenetML: ` + + (1,2) + (3,4) + + + + + + + + + + + + + + + + + + + + +

+ + + + + + + + + + + + +

+ + `, + }); + + await test_copy_points_lines_no_link(core); + }); + + it("copy string with no link, macros", async () => { + let core = await createTestCore({ + doenetML: ` +

Hello

+ $p1{name="p2" link="false"} + `, + }); + + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq("Hello"); + expect(stateVariables["/p2"].stateValues.text).eq("Hello"); + }); + + it("copy string with no link, with copySource", async () => { + let core = await createTestCore({ + doenetML: ` +

Hello

+

+ `, + }); + + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq("Hello"); + expect(stateVariables["/p2"].stateValues.text).eq("Hello"); + }); + + // This was causing a duplicate component name error + it("copy group with name inside with no link, macros", async () => { + let core = await createTestCore({ + doenetML: ` +

hello $m{name="q"}

+

$g{link="false"}

+ `, + }); + + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq("hello hello"); + expect(stateVariables["/p2"].stateValues.text).eq("hello hello"); + }); + + // This was causing a duplicate component name error + it("copy group with assignNames inside with no link, with copySource", async () => { + let core = await createTestCore({ + doenetML: ` +

hello $m{name="q"}

+

+ `, + }); + + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq("hello hello"); + expect(stateVariables["/p2"].stateValues.text).eq("hello hello"); + }); + + async function test_copy_group_copies_no_link(core) { + const stateVariables = await returnAllStateVariables(core); + + const names = [ + "", + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + ].map((l) => `/twox${l}`); + + for (let name of names) { + expect(stateVariables[name].stateValues.value.tree).eqls([ + "+", + "x", + "x", + ]); + } + } + + it("copy group with copies with no link, macros", async () => { + let core = await createTestCore({ + doenetML: ` + +

x+x

+ $twox{name="twoxa"} + $twox{name="twoxb"} +
+ + + $twox{name="twoxc"} + $twox{link="false" name="twoxd"} + + $twoxa{name="twoxe"} + $twoxa{link="false" name="twoxf"} + + $twoxe{name="twoxg"} + $twoxf{link="false" name="twoxh"} + + $twoxb{name="twoxi"} + $twoxb{link="false" name="twoxj"} + + $twoxi{name="twoxk"} + $twoxj{link="false" name="twoxl"} + + `, + }); + + await test_copy_group_copies_no_link(core); + }); + + it("copy group with copies with no link, with copySource", async () => { + let core = await createTestCore({ + doenetML: ` + +

x+x

+ + +
+ + + + + + + + + + + + + + + + + `, + }); + + await test_copy_group_copies_no_link(core); + }); + + async function test_copy_group_overwrite_attributes_no_link(core) { + async function check_items( + simplify1: "full" | "none", + simplify2: "full" | "none", + simplify3: "full" | "none", + ) { + const twoNone = ["+", "x", "x"]; + const twoSimp = ["*", 2, "x"]; + const threeNone = ["+", "x", "x", "x"]; + const threeSimp = ["*", 3, "x"]; + + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/twox"].stateValues.value.tree).eqls( + twoNone, + ); + expect(stateVariables["/twoxa"].stateValues.value.tree).eqls( + simplify1 === "full" ? twoSimp : twoNone, + ); + expect(stateVariables["/threex"].stateValues.value.tree).eqls( + simplify1 === "full" ? threeSimp : threeNone, + ); + + expect(stateVariables["/g2/twox"].stateValues.value.tree).eqls( + twoNone, + ); + expect(stateVariables["/g2/twoxa"].stateValues.value.tree).eqls( + simplify2 === "full" ? twoSimp : twoNone, + ); + expect(stateVariables["/g2/threex"].stateValues.value.tree).eqls( + simplify2 === "full" ? threeSimp : threeNone, + ); + + expect(stateVariables["/g3/twox"].stateValues.value.tree).eqls( + twoNone, + ); + expect(stateVariables["/g3/twoxa"].stateValues.value.tree).eqls( + simplify3 === "full" ? twoSimp : twoNone, + ); + expect(stateVariables["/g3/threex"].stateValues.value.tree).eqls( + simplify3 === "full" ? threeSimp : threeNone, + ); + } + + let simplify1: "full" | "none" = "full"; + let simplify2: "full" | "none" = "full"; + let simplify3: "full" | "none" = "full"; + + await check_items(simplify1, simplify2, simplify3); + + // change first simplify + simplify1 = "none"; + await updateTextInputValue({ + text: simplify1, + componentName: "/sim", + core, + }); + + await check_items(simplify1, simplify2, simplify3); + + // change second simplify + simplify2 = "none"; + await updateTextInputValue({ + text: simplify1, + componentName: "/g2/sim", + core, + }); + await check_items(simplify1, simplify2, simplify3); + + // change third simplify + simplify3 = "none"; + await updateTextInputValue({ + text: simplify1, + componentName: "/g3/sim", + core, + }); + await check_items(simplify1, simplify2, simplify3); + } + + it("copy group with copy overwriting attribute, no link, macros", async () => { + let core = await createTestCore({ + doenetML: ` + + + +

x+x + $twox{simplify="$sim" name="twoxa"} + x+x+x +

+
+ + $g{link="false" name="g2" newNamespace} + $g2{link="false" name="g3" newNamespace} + `, + }); + + await test_copy_group_overwrite_attributes_no_link(core); + }); + + it("copy group with copy overwriting attribute, no link, with copySource", async () => { + let core = await createTestCore({ + doenetML: ` + + + +

x+x + + x+x+x +

+
+ + + + `, + }); + + await test_copy_group_overwrite_attributes_no_link(core); + }); + + it("copy group, no link, with function adapted to curve", async () => { + let core = await createTestCore({ + doenetML: ` + a + + + x + + + + $g{link="false"} + + + `, + }); + + // just testing that page loads, i.e., that bug is removed so that don't get error + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/text1"].stateValues.text).eq("a"); + }); + + async function test_no_link_outside_component_from_attribute(core) { + async function check_items(text1: string, text2: string) { + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/g/w"].stateValues.text).eq(text1); + expect(stateVariables["/g/Plabel"].stateValues.text).eq(text1); + expect(stateVariables["/g/P"].stateValues.label).eq(text1); + expect(stateVariables["/g2/w"].stateValues.text).eq(text2); + expect(stateVariables["/g2/Plabel"].stateValues.text).eq(text2); + expect(stateVariables["/g2/P"].stateValues.label).eq(text2); + } + + await check_items("bye", "bye"); + + await updateTextInputValue({ + text: "hi", + componentName: "/external", + core, + }); + + await check_items("hi", "bye"); + } + + it("copy group, no link, copy to outside component from attribute, macros", async () => { + let core = await createTestCore({ + doenetML: ` + + + + $(/external.value{assignNames="w"}) + (a,b) + $(P.label{assignNames="Plabel"}) + + + $g{name="g2" link="false"} + `, + }); + + await test_no_link_outside_component_from_attribute(core); + }); + + it("copy group, no link, copy to outside component from attribute, with copySource", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + (a,b) + + + + + `, + }); + + await test_no_link_outside_component_from_attribute(core); + }); + + async function test_no_link_copy_internal_copy_source_alias(core) { + async function check_items(text1: string, text2: string) { + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/g/a/w"].stateValues.text).eq(text1); + expect(stateVariables["/g/a/Plabel"].stateValues.text).eq(text1); + expect(stateVariables["/g/a/P"].stateValues.label).eq(text1); + expect(stateVariables["/g2/a/w"].stateValues.text).eq(text2); + expect(stateVariables["/g2/a/Plabel"].stateValues.text).eq(text2); + expect(stateVariables["/g2/a/P"].stateValues.label).eq(text2); + } + + await check_items("hello", "hello"); + + await updateTextInputValue({ + text: "one", + componentName: "/g/ti", + core, + }); + await updateTextInputValue({ + text: "two", + componentName: "/g2/ti", + core, + }); + + await check_items("one", "two"); + } + + it("copy group, no link, internal copy to source alias is linked, macros", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + $ti + + + + + $g{name="g2" link="false"} + `, + }); + + await test_no_link_copy_internal_copy_source_alias(core); + }); + + it("copy group, no link, internal copy to source alias is linked, with copySource", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + $ti + + + + + + `, + }); + + await test_no_link_copy_internal_copy_source_alias(core); + }); + + async function test_no_link_external_absolute_source(core) { + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n"].stateValues.value).eq(2); + expect(stateVariables["/m"].stateValues.value).eq(4); + expect(stateVariables["/g/m1"].stateValues.value).eq(4); + expect(stateVariables["/g/m2"].stateValues.value).eq(4); + expect(stateVariables["/g2/m1"].stateValues.value).eq(4); + expect(stateVariables["/g2/m2"].stateValues.value).eq(4); + expect(stateVariables["/g3/m1"].stateValues.value).eq(4); + expect(stateVariables["/g3/m2"].stateValues.value).eq(4); + } + + it("copy no link containing external copies use absolute source, macros", async () => { + let core = await createTestCore({ + doenetML: ` + 2 + 2$n + + +

m = $(../m{name="m1"})

+

m = $(../m{name="m2" link="false"})

+
+ + $g{name="g2"} + $g{link="false" name="g3"} + `, + }); + + await test_no_link_external_absolute_source(core); + }); + + it("copy no link containing external copies use absolute source, with copySource", async () => { + let core = await createTestCore({ + doenetML: ` + 2 + 2$n + + +

m =

+

m =

+
+ + + + `, + }); + + await test_no_link_external_absolute_source(core); + }); + + async function test_dynamic_map_no_link_alias(core) { + async function check_items( + n1: number, + n2: number, + n3: number, + n4: number, + ) { + const stateVariables = await returnAllStateVariables(core); + if ((n1) => 1) { + expect(stateVariables["/section1/p1"].stateValues.text).eq( + "i=1, v=11", + ); + expect(stateVariables["/section5/p1"].stateValues.text).eq( + "i=1, v=11", + ); + expect(stateVariables["/p1a"].stateValues.text).eq("i=1, v=11"); + expect(stateVariables["/section7/p1"].stateValues.text).eq( + "i=1, v=11", + ); + } else { + isUndefinedOrInactive(stateVariables["/section1/p1"]); + isUndefinedOrInactive(stateVariables["/section5/p1"]); + isUndefinedOrInactive(stateVariables["/p1a"]); + isUndefinedOrInactive(stateVariables["/section7/p1"]); + } + if (n1 >= 2) { + expect(stateVariables["/section1/p2"].stateValues.text).eq( + "i=2, v=12", + ); + expect(stateVariables["/section5/p2"].stateValues.text).eq( + "i=2, v=12", + ); + expect(stateVariables["/p2a"].stateValues.text).eq("i=2, v=12"); + expect(stateVariables["/section7/p2"].stateValues.text).eq( + "i=2, v=12", + ); + } else { + isUndefinedOrInactive(stateVariables["/section1/p2"]); + isUndefinedOrInactive(stateVariables["/section5/p2"]); + isUndefinedOrInactive(stateVariables["/p2a"]); + isUndefinedOrInactive(stateVariables["/section7/p2"]); + } + if (n1 >= 3) { + expect(stateVariables["/section1/p3"].stateValues.text).eq( + "i=3, v=13", + ); + expect(stateVariables["/section5/p3"].stateValues.text).eq( + "i=3, v=13", + ); + expect(stateVariables["/p3a"].stateValues.text).eq("i=3, v=13"); + expect(stateVariables["/section7/p3"].stateValues.text).eq( + "i=3, v=13", + ); + } else { + isUndefinedOrInactive(stateVariables["/section1/p3"]); + isUndefinedOrInactive(stateVariables["/section5/p3"]); + isUndefinedOrInactive(stateVariables["/p3a"]); + isUndefinedOrInactive(stateVariables["/section7/p3"]); + } + if (n1 >= 4) { + expect(stateVariables["/section1/p4"].stateValues.text).eq( + "i=4, v=14", + ); + expect(stateVariables["/section5/p4"].stateValues.text).eq( + "i=4, v=14", + ); + expect(stateVariables["/p4a"].stateValues.text).eq("i=4, v=14"); + expect(stateVariables["/section7/p4"].stateValues.text).eq( + "i=4, v=14", + ); + } else { + isUndefinedOrInactive(stateVariables["/section1/p4"]); + isUndefinedOrInactive(stateVariables["/section5/p4"]); + isUndefinedOrInactive(stateVariables["/p4a"]); + isUndefinedOrInactive(stateVariables["/section7/p4"]); + } + + if ((n2) => 1) { + expect(stateVariables["/section2/p1"].stateValues.text).eq( + "i=1, v=11", + ); + } else { + isUndefinedOrInactive(stateVariables["/section2/p1"]); + } + if (n2 >= 2) { + expect(stateVariables["/section2/p2"].stateValues.text).eq( + "i=2, v=12", + ); + } else { + isUndefinedOrInactive(stateVariables["/section2/p2"]); + } + if (n2 >= 3) { + expect(stateVariables["/section2/p3"].stateValues.text).eq( + "i=3, v=13", + ); + } else { + isUndefinedOrInactive(stateVariables["/section2/p3"]); + } + if (n2 >= 4) { + expect(stateVariables["/section2/p4"].stateValues.text).eq( + "i=4, v=14", + ); + } else { + isUndefinedOrInactive(stateVariables["/section2/p4"]); + } + + if ((n3) => 1) { + expect(stateVariables["/p1"].stateValues.text).eq("i=1, v=11"); + } else { + isUndefinedOrInactive(stateVariables["/p1"]); + } + if (n3 >= 2) { + expect(stateVariables["/p2"].stateValues.text).eq("i=2, v=12"); + } else { + isUndefinedOrInactive(stateVariables["/p2"]); + } + if (n3 >= 3) { + expect(stateVariables["/p3"].stateValues.text).eq("i=3, v=13"); + } else { + isUndefinedOrInactive(stateVariables["/p3"]); + } + if (n3 >= 4) { + expect(stateVariables["/p4"].stateValues.text).eq("i=4, v=14"); + } else { + isUndefinedOrInactive(stateVariables["/p4"]); + } + + if ((n4) => 1) { + expect(stateVariables["/section4/p1"].stateValues.text).eq( + "i=1, v=11", + ); + } else { + isUndefinedOrInactive(stateVariables["/section4/p1"]); + } + if (n4 >= 2) { + expect(stateVariables["/section4/p2"].stateValues.text).eq( + "i=2, v=12", + ); + } else { + isUndefinedOrInactive(stateVariables["/section4/p2"]); + } + if (n4 >= 3) { + expect(stateVariables["/section4/p3"].stateValues.text).eq( + "i=3, v=13", + ); + } else { + isUndefinedOrInactive(stateVariables["/section4/p3"]); + } + if (n4 >= 4) { + expect(stateVariables["/section4/p4"].stateValues.text).eq( + "i=4, v=14", + ); + } else { + isUndefinedOrInactive(stateVariables["/section4/p4"]); + } + } + + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/section1"].stateValues.title).eq("Section 1"); + expect(stateVariables["/section2"].stateValues.title).eq("Section 2"); + expect(stateVariables["/section3"].stateValues.title).eq("Section 3"); + expect(stateVariables["/section4"].stateValues.title).eq("Section 4"); + expect(stateVariables["/section5"].stateValues.title).eq("Section 5"); + expect(stateVariables["/section6"].stateValues.title).eq("Section 6"); + expect(stateVariables["/section7"].stateValues.title).eq("Section 7"); + + await check_items(2, 2, 2, 2); + + await core.requestAction({ + componentName: "/section1/addP", + actionName: "updateValue", + args: {}, + event: null, + }); + await check_items(3, 2, 2, 2); + + await core.requestAction({ + componentName: "/section7/removeP", + actionName: "updateValue", + args: {}, + event: null, + }); + await check_items(2, 2, 2, 2); + + await core.requestAction({ + componentName: "/section4/addP", + actionName: "updateValue", + args: {}, + event: null, + }); + await check_items(2, 2, 2, 3); + + await core.requestAction({ + componentName: "/section4/removeP", + actionName: "updateValue", + args: {}, + event: null, + }); + await check_items(2, 2, 2, 2); + } + + it("copy dynamic map no link, check aliases, macros", async () => { + let core = await createTestCore({ + doenetML: ` +
+ + 2 + + + + + + + + + + + + +
+ +
+ $(../section1/map1{link='false' assignNames='(p1) (p2) (p3) (p4)'}) +
+ +
+ $(section1/map1{link='false' assignNames='(p1) (p2) (p3) (p4)'}) +
+ + $section1{link='false' name="section4"} + +
+ $(../section1/map1{assignNames='(p1) (p2) (p3) (p4)'}) +
+ +
+ $(section1/map1{assignNames='(p1a) (p2a) (p3a) (p4a)'}) +
+ + $section1{name="section7"} + + `, + }); + + await test_dynamic_map_no_link_alias(core); + }); + + it("copy dynamic map no link, check aliases, with copySource", async () => { + let core = await createTestCore({ + doenetML: ` + + +
+ + 2 + + + + + + + + + + + + +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ + `, + }); + + await test_dynamic_map_no_link_alias(core); + }); + + it("copy map source with no link, macros", async () => { + let core = await createTestCore({ + doenetML: ` +

Number of iterations:

+ + + + + + + + + + + + `, + }); + + async function check_items( + A?: number[], + B?: number[], + C?: number[], + D?: number[], + E?: number[], + F?: number[], + ) { + const stateVariables = await returnAllStateVariables(core); + + if (A) { + expect( + stateVariables["/A"].stateValues.xs.map((x) => x.tree), + ).eqls(A); + } else { + isUndefinedOrInactive(stateVariables["/A"]); + } + if (B) { + expect( + stateVariables["/B"].stateValues.xs.map((x) => x.tree), + ).eqls(B); + } else { + isUndefinedOrInactive(stateVariables["/B"]); + } + if (C) { + expect( + stateVariables["/C"].stateValues.xs.map((x) => x.tree), + ).eqls(C); + } else { + isUndefinedOrInactive(stateVariables["/C"]); + } + if (D) { + expect( + stateVariables["/D"].stateValues.xs.map((x) => x.tree), + ).eqls(D); + } else { + isUndefinedOrInactive(stateVariables["/D"]); + } + if (E) { + expect( + stateVariables["/E"].stateValues.xs.map((x) => x.tree), + ).eqls(E); + } else { + isUndefinedOrInactive(stateVariables["/E"]); + } + if (F) { + expect( + stateVariables["/F"].stateValues.xs.map((x) => x.tree), + ).eqls(F); + } else { + isUndefinedOrInactive(stateVariables["/F"]); + } + } + + await check_items(); + + await updateMathInputValue({ latex: "1", componentName: "/n", core }); + await check_items([1, 2], [3, 4], [5, 6]); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/A", + args: { x: 9, y: 0 }, + event: null, + }); + await core.requestAction({ + actionName: "movePoint", + componentName: "/B", + args: { x: 1, y: 8 }, + event: null, + }); + await core.requestAction({ + actionName: "movePoint", + componentName: "/C", + args: { x: 7, y: 2 }, + event: null, + }); + + await check_items([9, 0], [1, 8], [7, 2]); + + await updateMathInputValue({ latex: "2", componentName: "/n", core }); + + await check_items([9, 0], [1, 8], [7, 2], [2, 3], [4, 5], [6, 7]); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/D", + args: { x: 0, y: 10 }, + event: null, + }); + await core.requestAction({ + actionName: "movePoint", + componentName: "/E", + args: { x: 9, y: 1 }, + event: null, + }); + await core.requestAction({ + actionName: "movePoint", + componentName: "/F", + args: { x: 2, y: 8 }, + event: null, + }); + + await check_items([9, 0], [1, 8], [7, 2], [0, 10], [9, 1], [2, 8]); + + await updateMathInputValue({ latex: "0", componentName: "/n", core }); + await check_items(); + + await updateMathInputValue({ latex: "2", componentName: "/n", core }); + + await check_items([9, 0], [1, 8], [7, 2], [0, 10], [9, 1], [2, 8]); + }); + + it("copy no-link of a copy prop", async () => { + let core = await createTestCore({ + doenetML: ` + x + + + + $xval + $xvalnl + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/x"].stateValues.value.tree).eq("x"); + expect(stateVariables["/xval"].stateValues.value.tree).eq("x"); + expect(stateVariables["/xvalnl"].stateValues.value.tree).eq("x"); + + await updateMathInputValue({ latex: "y", componentName: "/mi1", core }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/x"].stateValues.value.tree).eq("y"); + expect(stateVariables["/xval"].stateValues.value.tree).eq("y"); + expect(stateVariables["/xvalnl"].stateValues.value.tree).eq("x"); + + await updateMathInputValue({ latex: "z", componentName: "/mi2", core }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/x"].stateValues.value.tree).eq("y"); + expect(stateVariables["/xval"].stateValues.value.tree).eq("y"); + expect(stateVariables["/xvalnl"].stateValues.value.tree).eq("z"); + }); + + it("copy no-link of a copy prop 2", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + + + + + + + + + `, + }); + + async function check_items({ + v1, + v1nl, + v2nl, + v3nl, + }: { + v1: number[]; + v1nl: number[]; + v2nl: number[]; + v3nl: number[]; + }) { + const stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/v1"].stateValues.xs.map((x) => x.tree), + ).eqls(v1); + expect( + stateVariables["/v1nl"].stateValues.xs.map((x) => x.tree), + ).eqls(v1nl); + expect( + stateVariables["/v2nl"].stateValues.xs.map((x) => x.tree), + ).eqls(v2nl); + expect( + stateVariables["/v3nl"].stateValues.xs.map((x) => x.tree), + ).eqls(v3nl); + } + + let v1 = [0, 1], + v1nl = [0, 1], + v2nl = [0, 1], + v3nl = [0, 1]; + + await check_items({ v1, v1nl, v2nl, v3nl }); + + // Move v1 + v1 = [2, 3]; + await core.requestAction({ + actionName: "movePoint", + componentName: "/v1", + args: { x: v1[0], y: v1[1] }, + event: null, + }); + await check_items({ v1, v1nl, v2nl, v3nl }); + + // Move v1nl + v1nl = [3, 4]; + await core.requestAction({ + actionName: "movePoint", + componentName: "/v1nl", + args: { x: v1nl[0], y: v1nl[1] }, + event: null, + }); + await check_items({ v1, v1nl, v2nl, v3nl }); + + // Move v2nl + v2nl = [4, 5]; + await core.requestAction({ + actionName: "movePoint", + componentName: "/v2nl", + args: { x: v2nl[0], y: v2nl[1] }, + event: null, + }); + await check_items({ v1, v1nl, v2nl, v3nl }); + + // Move v3nl + v3nl = [5, 6]; + await core.requestAction({ + actionName: "movePoint", + componentName: "/v3nl", + args: { x: v3nl[0], y: v3nl[1] }, + event: null, + }); + await check_items({ v1, v1nl, v2nl, v3nl }); + }); + + it("copy of template source maintained when withheld, macros", async () => { + let core = await createTestCore({ + doenetML: ` +

Number of points:

+ + + + + + + + +

A_1 = $(t1/A{displayDigits="3"})

+

A_2 = $(t2/A{displayDigits="3"})

+ + `, + }); + + async function check_items(A1latex: string, A2latex: string) { + const stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/m1"].stateValues.latex)).eq( + `A_1=${A1latex}`, + ); + expect(cleanLatex(stateVariables["/m2"].stateValues.latex)).eq( + `A_2=${A2latex}`, + ); + } + + let A1 = [1, 1], + A2 = [2, 1]; + + await check_items("", ""); + + // Add point + + await updateMathInputValue({ latex: "1", componentName: "/n", core }); + + await check_items(`(${A1.join(",")})`, ""); + + // Move point + A1 = [-3, 7]; + await core.requestAction({ + actionName: "movePoint", + componentName: "/t1/A", + args: { x: A1[0], y: A1[1] }, + event: null, + }); + + await check_items(`(${A1.join(",")})`, ""); + + // Remove point + await updateMathInputValue({ latex: "0", componentName: "/n", core }); + await check_items("", ""); + + // Remember coordinates when restore point since copy was maintained + await updateMathInputValue({ latex: "1", componentName: "/n", core }); + + await check_items(`(${A1.join(",")})`, ""); + + // Add second point + await updateMathInputValue({ latex: "2", componentName: "/n", core }); + await check_items(`(${A1.join(",")})`, `(${A2.join(",")})`); + + // Move second point + A2 = [5, -4]; + await core.requestAction({ + actionName: "movePoint", + componentName: "/t2/A", + args: { x: A2[0], y: A2[1] }, + event: null, + }); + await check_items(`(${A1.join(",")})`, `(${A2.join(",")})`); + + // Remove both points + await updateMathInputValue({ latex: "0", componentName: "/n", core }); + await check_items("", ""); + + // Remember coordinates of both points + await updateMathInputValue({ latex: "2", componentName: "/n", core }); + await check_items(`(${A1.join(",")})`, `(${A2.join(",")})`); + }); + + it("trim whitespace off source, with copySource", async () => { + let core = await createTestCore({ + doenetML: ` + Hello +

there

+ `, + }); + + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/hi"].stateValues.text).eq("Hello"); + expect(stateVariables["/p1"].stateValues.text).eq("Hello there"); + }); + + async function test_copy_group_with_numbers(core, name_prefix = "") { + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables[`${name_prefix}/n1`].stateValues.value).eq(1); + expect(stateVariables[`${name_prefix}/n2`].stateValues.value).eq(2); + expect(stateVariables["/n3"].stateValues.value).eq(3); + expect(stateVariables[`/p2${name_prefix}/n1`].stateValues.value).eq(1); + expect(stateVariables[`/p2${name_prefix}/n2`].stateValues.value).eq(2); + expect(stateVariables["/p2/n3"].stateValues.value).eq(3); + expect(stateVariables[`/p2a${name_prefix}/n1`].stateValues.value).eq(1); + expect(stateVariables[`/p2a${name_prefix}/n2`].stateValues.value).eq(2); + expect(stateVariables["/p2a/n3"].stateValues.value).eq(3); + expect(stateVariables[`/p2b${name_prefix}/n1`].stateValues.value).eq(1); + expect(stateVariables[`/p2b${name_prefix}/n2`].stateValues.value).eq(2); + expect(stateVariables["/p2b/n3"].stateValues.value).eq(3); + expect(stateVariables[`/s1b/p2${name_prefix}/n1`].stateValues.value).eq( + 1, + ); + expect(stateVariables[`/s1b/p2${name_prefix}/n2`].stateValues.value).eq( + 2, + ); + expect(stateVariables["/s1b/p2/n3"].stateValues.value).eq(3); + + expect(stateVariables["/p1"].stateValues.text).eq("values: 1 2 3"); + expect(stateVariables["/p2a"].stateValues.text).eq("values: 1 2 3"); + expect(stateVariables["/p2b"].stateValues.text).eq("values: 1 2 3"); + expect(stateVariables["/s1b/p2"].stateValues.text).eq("values: 1 2 3"); + + expect( + stateVariables["/section1"].activeChildren.map( + (x) => x.componentName, + ), + ).eqls(["/p2"]); + expect( + stateVariables["/s1a"].activeChildren.map((x) => x.componentType), + ).eqls(["p"]); + expect( + stateVariables["/s1b"].activeChildren.map((x) => x.componentName), + ).eqls(["/s1b/p2"]); + + let c2p = stateVariables["/_document1"].activeChildren[5].componentName; + let c4p = stateVariables["/_document1"].activeChildren[9].componentName; + let c6p = + stateVariables["/_document1"].activeChildren[13].componentName; + let c7s = + stateVariables["/_document1"].activeChildren[15].componentName; + let c9s = + stateVariables["/_document1"].activeChildren[19].componentName; + + expect(stateVariables[c2p].stateValues.text).eq("values: 1 2 3"); + expect(stateVariables[c4p].stateValues.text).eq("values: 1 2 3"); + expect(stateVariables[c6p].stateValues.text).eq("values: 1 2 3"); + + expect( + stateVariables[c7s].activeChildren.map((x) => x.componentType), + ).eqls(["p"]); + + expect( + stateVariables[c9s].activeChildren.map((x) => x.componentType), + ).eqls(["p"]); + + // c2p's children should have gotten unique names (so begin with two underscores) + let c2pChildNames = stateVariables[c2p].activeChildren + .filter((x) => x.componentName) + .map((x) => x.componentName); + expect(c2pChildNames[0].slice(0, 3)).eq("/__"); + expect(c2pChildNames[1].slice(0, 3)).eq("/__"); + expect(c2pChildNames[2].slice(0, 3)).eq("/__"); + expect(stateVariables[c2pChildNames[0]].stateValues.value).eq(1); + expect(stateVariables[c2pChildNames[1]].stateValues.value).eq(2); + expect(stateVariables[c2pChildNames[2]].stateValues.value).eq(3); + + // c4p's children should have gotten unique names (so begin with two underscores) + let c4pChildNames = stateVariables[c4p].activeChildren + .filter((x) => x.componentName) + .map((x) => x.componentName); + expect(c4pChildNames[0].slice(0, 3)).eq("/__"); + expect(c4pChildNames[1].slice(0, 3)).eq("/__"); + expect(c4pChildNames[2].slice(0, 3)).eq("/__"); + expect(stateVariables[c4pChildNames[0]].stateValues.value).eq(1); + expect(stateVariables[c4pChildNames[1]].stateValues.value).eq(2); + expect(stateVariables[c4pChildNames[2]].stateValues.value).eq(3); + + // c6p's children should have gotten unique names (so begin with two underscores) + let c6pChildNames = stateVariables[c6p].activeChildren + .filter((x) => x.componentName) + .map((x) => x.componentName); + expect(c6pChildNames[0].slice(0, 3)).eq("/__"); + expect(c6pChildNames[1].slice(0, 3)).eq("/__"); + expect(c6pChildNames[2].slice(0, 3)).eq("/__"); + expect(stateVariables[c6pChildNames[0]].stateValues.value).eq(1); + expect(stateVariables[c6pChildNames[1]].stateValues.value).eq(2); + expect(stateVariables[c6pChildNames[2]].stateValues.value).eq(3); + + // c7s's grandchildren should have gotten unique names (so begin with two underscores) + let c7sChildName = stateVariables[c7s].activeChildren.filter( + (x) => x.componentName, + )[0].componentName; + let c7sGrandChildNames = stateVariables[c7sChildName].activeChildren + .filter((x) => x.componentName) + .map((x) => x.componentName); + + expect(c7sGrandChildNames[0].slice(0, 3)).eq("/__"); + expect(c7sGrandChildNames[1].slice(0, 3)).eq("/__"); + expect(c7sGrandChildNames[2].slice(0, 3)).eq("/__"); + expect(stateVariables[c7sGrandChildNames[0]].stateValues.value).eq(1); + expect(stateVariables[c7sGrandChildNames[1]].stateValues.value).eq(2); + expect(stateVariables[c7sGrandChildNames[2]].stateValues.value).eq(3); + + // s1a's grandchildren should have gotten unique names (so begin with two underscores) + let s1aChildName = stateVariables["/s1a"].activeChildren.filter( + (x) => x.componentName, + )[0].componentName; + let s1aGrandChildNames = stateVariables[s1aChildName].activeChildren + .filter((x) => x.componentName) + .map((x) => x.componentName); + + expect(s1aGrandChildNames[0].slice(0, 3)).eq("/__"); + expect(s1aGrandChildNames[1].slice(0, 3)).eq("/__"); + expect(s1aGrandChildNames[2].slice(0, 3)).eq("/__"); + expect(stateVariables[s1aGrandChildNames[0]].stateValues.value).eq(1); + expect(stateVariables[s1aGrandChildNames[1]].stateValues.value).eq(2); + expect(stateVariables[s1aGrandChildNames[2]].stateValues.value).eq(3); + + // c9s's grandchildren should have gotten unique names (so begin with two underscores) + let c9sChildName = stateVariables[c9s].activeChildren.filter( + (x) => x.componentName, + )[0].componentName; + let c9sGrandChildNames = stateVariables[c9sChildName].activeChildren + .filter((x) => x.componentName) + .map((x) => x.componentName); + + expect(c9sGrandChildNames[0].slice(0, 3)).eq("/__"); + expect(c9sGrandChildNames[1].slice(0, 3)).eq("/__"); + expect(c9sGrandChildNames[2].slice(0, 3)).eq("/__"); + expect(stateVariables[c9sGrandChildNames[0]].stateValues.value).eq(1); + expect(stateVariables[c9sGrandChildNames[1]].stateValues.value).eq(2); + expect(stateVariables[c9sGrandChildNames[2]].stateValues.value).eq(3); + + // s1b's grandchildren should have retained their original names + let s1bChildName = stateVariables["/s1b"].activeChildren.filter( + (x) => x.componentName, + )[0].componentName; + let s1bGrandChildNames = stateVariables[s1bChildName].activeChildren + .filter((x) => x.componentName) + .map((x) => x.componentName); + + expect(s1bGrandChildNames[0]).eq(`/s1b/p2${name_prefix}/n1`); + expect(s1bGrandChildNames[1]).eq(`/s1b/p2${name_prefix}/n2`); + expect(s1bGrandChildNames[2]).eq("/s1b/p2/n3"); + expect(stateVariables[s1bGrandChildNames[0]].stateValues.value).eq(1); + expect(stateVariables[s1bGrandChildNames[1]].stateValues.value).eq(2); + expect(stateVariables[s1bGrandChildNames[2]].stateValues.value).eq(3); + } + + it("copy with newNamespace and name retains original names, even with group that assigns name to just one number, macros", async () => { + let core = await createTestCore({ + doenetML: ` +

values: 1 2 3

+ +
$p1{newNamespace name="p2"}
+ + $p2 + $p2{name="p2a"} + $p2{newNamespace} + $p2{newNamespace name="p2b"} + $p2a{newNamespace} + + $section1 + $section1{name="s1a"} + $section1{newNamespace} + $section1{newNamespace name="s1b"} + + `, + }); + + await test_copy_group_with_numbers(core); + }); + + it("copy with newNamespace and name retains original names, even with group, macros", async () => { + let core = await createTestCore({ + doenetML: ` +

values: 1 2 3

+ +
$p1{newNamespace name="p2"}
+ + $p2 + $p2{name="p2a"} + $p2{newNamespace} + $p2{newNamespace name="p2b"} + $p2a{newNamespace} + + $section1 + $section1{name="s1a"} + $section1{newNamespace} + $section1{newNamespace name="s1b"} + + `, + }); + + await test_copy_group_with_numbers(core); + }); + + it("copy with newNamespace and name retains original names, even with group that assigns names, macros", async () => { + let core = await createTestCore({ + doenetML: ` +

values: 1 2 3

+ +
$p1{newNamespace name="p2"}
+ + $p2 + $p2{name="p2a"} + $p2{newNamespace} + $p2{newNamespace name="p2b"} + $p2a{newNamespace} + + $section1 + $section1{name="s1a"} + $section1{newNamespace} + $section1{newNamespace name="s1b"} + + `, + }); + + await test_copy_group_with_numbers(core); + }); + + it("copy with newNamespace and name retains original names, even with group that has new namespace, macros", async () => { + let core = await createTestCore({ + doenetML: ` +

values: 1 2 3

+ +
$p1{newNamespace name="p2"}
+ + $p2 + $p2{name="p2a"} + $p2{newNamespace} + $p2{newNamespace name="p2b"} + $p2a{newNamespace} + + $section1 + $section1{name="s1a"} + $section1{newNamespace} + $section1{newNamespace name="s1b"} + + `, + }); + + await test_copy_group_with_numbers(core, "/grp"); + }); + + it("copy with newNamespace and name retains original names, even with group that has new namespace and assigns names, macros", async () => { + let core = await createTestCore({ + doenetML: ` +

values: 1 2 3

+ +
$p1{newNamespace name="p2"}
+ + $p2 + $p2{name="p2a"} + $p2{newNamespace} + $p2{newNamespace name="p2b"} + $p2a{newNamespace} + + $section1 + $section1{name="s1a"} + $section1{newNamespace} + $section1{newNamespace name="s1b"} + + `, + }); + + await test_copy_group_with_numbers(core, "/grp"); + }); + + it("copy with newNamespace and name retains original names, even with group, wrapped in nested groups and copied with variable componentIndex", async () => { + let core = await createTestCore({ + doenetML: ` + + + +

values: 1 2 3

+ +
$p1{newNamespace name="p2"}
+ + $p2{name="p2a"} + $p2{newNamespace name="p2b"} + + $section1{newNamespace name="s1b"} +
+ +

values: 4 5 6

+ +
$p1{newNamespace name="p2"}
+ + $p2{name="p2a"} + $p2{newNamespace name="p2b"} + + $section1{newNamespace name="s1b"} +
+
+ + $grp[$n]{name="thegrp"} + + + `, + }); + + async function test_group( + name_prefix: string, + n1: number, + n2: number, + n3: number, + ) { + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables[`${name_prefix}/n1`].stateValues.value).eq( + n1, + ); + expect(stateVariables[`${name_prefix}/n2`].stateValues.value).eq( + n2, + ); + expect(stateVariables[`${name_prefix}/n3`].stateValues.value).eq( + n3, + ); + expect(stateVariables[`${name_prefix}/p2/n1`].stateValues.value).eq( + n1, + ); + expect(stateVariables[`${name_prefix}/p2/n2`].stateValues.value).eq( + n2, + ); + expect(stateVariables[`${name_prefix}/p2/n3`].stateValues.value).eq( + n3, + ); + expect( + stateVariables[`${name_prefix}/p2a/n1`].stateValues.value, + ).eq(n1); + expect( + stateVariables[`${name_prefix}/p2a/n2`].stateValues.value, + ).eq(n2); + expect( + stateVariables[`${name_prefix}/p2a/n3`].stateValues.value, + ).eq(n3); + expect( + stateVariables[`${name_prefix}/p2b/n1`].stateValues.value, + ).eq(n1); + expect( + stateVariables[`${name_prefix}/p2b/n2`].stateValues.value, + ).eq(n2); + expect( + stateVariables[`${name_prefix}/p2b/n3`].stateValues.value, + ).eq(n3); + expect( + stateVariables[`${name_prefix}/s1b/p2/n1`].stateValues.value, + ).eq(n1); + expect( + stateVariables[`${name_prefix}/s1b/p2/n2`].stateValues.value, + ).eq(n2); + expect( + stateVariables[`${name_prefix}/s1b/p2/n3`].stateValues.value, + ).eq(n3); + + expect(stateVariables[`${name_prefix}/p1`].stateValues.text).eq( + `values: ${n1} ${n2} ${n3}`, + ); + expect(stateVariables[`${name_prefix}/p2a`].stateValues.text).eq( + `values: ${n1} ${n2} ${n3}`, + ); + expect(stateVariables[`${name_prefix}/p2b`].stateValues.text).eq( + `values: ${n1} ${n2} ${n3}`, + ); + expect(stateVariables[`${name_prefix}/s1b/p2`].stateValues.text).eq( + `values: ${n1} ${n2} ${n3}`, + ); + + expect( + stateVariables[`${name_prefix}/section1`].activeChildren.map( + (x) => x.componentName, + ), + ).eqls([`${name_prefix}/p2`]); + expect( + stateVariables[`${name_prefix}/s1b`].activeChildren.map( + (x) => x.componentName, + ), + ).eqls([`${name_prefix}/s1b/p2`]); + } + + // check g1 + + await test_group("/g1", 1, 2, 3); + + // check g2 + + await test_group("/g2", 4, 5, 6); + + // check thegrp + await test_group("/thegrp", 1, 2, 3); + + // Change index for thegrp + await updateMathInputValue({ latex: "2", componentName: "/n", core }); + + await test_group("/thegrp", 4, 5, 6); + + // Change to invalid index for thegrp + await updateMathInputValue({ latex: "3", componentName: "/n", core }); + + let stateVariable = await returnAllStateVariables(core); + + expect(stateVariable["/thegrp"]).eq(undefined); + + // Change back to index 1 for thegrp + await updateMathInputValue({ latex: "1", componentName: "/n", core }); + + await test_group("/thegrp", 1, 2, 3); + }); + + it("copy group of groups retains name", async () => { + let core = await createTestCore({ + doenetML: ` + 1 2 3456 + + $grp{name="grp2"} + + + + + + + `, + }); + + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/grp/num1"].stateValues.value).eq(1); + expect(stateVariables["/grp/num2"].stateValues.value).eq(2); + expect(stateVariables["/grp/num3"].stateValues.value).eq(3); + expect(stateVariables["/grp/num4"].stateValues.value).eq(4); + expect(stateVariables["/grp/num5"].stateValues.value).eq(5); + expect(stateVariables["/grp/num6"].stateValues.value).eq(6); + + expect(stateVariables["/grp2/num1"].stateValues.value).eq(1); + expect(stateVariables["/grp2/num2"].stateValues.value).eq(2); + expect(stateVariables["/grp2/num3"].stateValues.value).eq(3); + expect(stateVariables["/grp2/num4"].stateValues.value).eq(4); + expect(stateVariables["/grp2/num5"].stateValues.value).eq(5); + expect(stateVariables["/grp2/num6"].stateValues.value).eq(6); + + expect(stateVariables["/grp3/num1"].stateValues.value).eq(1); + expect(stateVariables["/grp3/num2"].stateValues.value).eq(2); + expect(stateVariables["/grp3/num3"].stateValues.value).eq(3); + expect(stateVariables["/grp3/num4"].stateValues.value).eq(4); + expect(stateVariables["/grp3/num5"].stateValues.value).eq(5); + expect(stateVariables["/grp3/num6"].stateValues.value).eq(6); + + expect(stateVariables["/grp4/num3"].stateValues.value).eq(3); + expect(stateVariables["/grp4/num4"].stateValues.value).eq(4); + expect(stateVariables["/grp4/num5"].stateValues.value).eq(5); + expect(stateVariables["/grp4/num6"].stateValues.value).eq(6); + + expect(stateVariables["/grp5/num3"].stateValues.value).eq(3); + expect(stateVariables["/grp5/num4"].stateValues.value).eq(4); + expect(stateVariables["/grp5/num5"].stateValues.value).eq(5); + expect(stateVariables["/grp5/num6"].stateValues.value).eq(6); + }); + + it("copy group, does not avoid name collision when assign subnames", async () => { + let core = await createTestCore({ + doenetML: ` + 1 2 + +

$grp{assignNames="num2"}

+ + + `, + }); + + let errorWarnings = core.errorWarnings; + + expect(errorWarnings.errors.length).eq(1); + expect(errorWarnings.warnings.length).eq(0); + + expect(errorWarnings.errors[0].message).eq( + "Duplicate component name: num2.", + ); + }); + + it("copy p with newNamespace, does not avoid name collision when assignnames", async () => { + let core = await createTestCore({ + doenetML: ` +

Hello

+ $p{newNamespace name="hello"} + + `, + }); + + let errorWarnings = core.errorWarnings; + + expect(errorWarnings.errors.length).eq(1); + expect(errorWarnings.warnings.length).eq(0); + + expect(errorWarnings.errors[0].message).eq( + "Duplicate component name: hello.", + ); + }); + + it("copy point with math attribute, duplicate component name message uses point name", async () => { + let core = await createTestCore({ + doenetML: ` + + $P{name="P" y="2" } + `, + }); + + let errorWarnings = core.errorWarnings; + + expect(errorWarnings.errors.length).eq(1); + expect(errorWarnings.warnings.length).eq(0); + + expect(errorWarnings.errors[0].message).eq( + "Duplicate component name: P.", + ); + }); + + async function test_copy_component_index(core: any, force_values: boolean) { + async function check_items({ + x1, + y1, + x2, + y2, + comp, + }: { + x1: number; + y1: number; + x2: number; + y2: number; + comp?: number; + }) { + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/A"].stateValues.xs.map((x) => x.tree)).eqls( + [x1, y1], + ); + expect(stateVariables["/B"].stateValues.xs.map((x) => x.tree)).eqls( + [x2, y2], + ); + + if (comp === 1 || comp === 2) { + let xc = comp === 1 ? x1 : x2; + let yc = comp === 1 ? y1 : y2; + + expect( + stateVariables["/A2"].stateValues.xs.map((x) => x.tree), + ).eqls([xc, yc]); + expect( + stateVariables["/g3/A2"].stateValues.xs.map((x) => x.tree), + ).eqls([xc, yc]); + expect(stateVariables["/Ax"].stateValues.value.tree).eq(xc); + expect(stateVariables["/al2/Ax"].stateValues.value.tree).eq(xc); + } else if (force_values) { + expect(stateVariables["/Ax"].stateValues.value.tree).eq( + "\uff3f", + ); + expect(stateVariables["/al2/Ax"].stateValues.value.tree).eq( + "\uff3f", + ); + } else { + expect(stateVariables["/A2"]).eq(undefined); + expect(stateVariables["/g3/A2"]).eq(undefined); + expect(stateVariables["/Ax"]).eq(undefined); + expect(stateVariables["/al2/Ax"]).eq(undefined); + } + } + + let x1 = 1, + y1 = 2, + x2 = 3, + y2 = 4; + + await check_items({ x1, y1, x2, y2 }); + + // restrict collection to first component + + await updateMathInputValue({ latex: "1", componentName: "/n", core }); + + await check_items({ x1, y1, x2, y2, comp: 1 }); + + // move copied point + x1 = 9; + y1 = -5; + await core.requestAction({ + actionName: "movePoint", + componentName: "/A2", + args: { x: x1, y: y1 }, + event: null, + }); + + await check_items({ x1, y1, x2, y2, comp: 1 }); + + // restrict collection to second component + + await updateMathInputValue({ latex: "2", componentName: "/n", core }); + + await check_items({ x1, y1, x2, y2, comp: 2 }); + + // move double copied point + x2 = 0; + y2 = 8; + await core.requestAction({ + actionName: "movePoint", + componentName: "/g3/A2", + args: { x: x2, y: y2 }, + event: null, + }); + + await check_items({ x1, y1, x2, y2, comp: 2 }); + } + + it("copy componentIndex, array notation, macros", async () => { + let core = await createTestCore({ + doenetML: ` +

n:

+ + + (1,2) + (3,4) + + + + + + + + $(col[$n]{name="A2"}) + + + $g2{name="g3" newNamespace} + + $(col[$n].x{assignNames="Ax"}) + + $al{name="al2" newNamespace} + + `, + }); + + await test_copy_component_index(core, false); + }); + + it("copy componentIndex, with copySource, array notation", async () => { + let core = await createTestCore({ + doenetML: ` +

n:

+ + + (1,2) + (3,4) + + + + + + + + + + + + + + + + + `, + }); + + await test_copy_component_index(core, true); + }); + + async function test_copy_prop_component_index( + core: any, + force_values: boolean, + ) { + async function check_items({ + x1, + y1, + x2, + y2, + propIndex, + componentIndex, + }: { + x1: number; + y1: number; + x2: number; + y2: number; + propIndex?: number; + componentIndex?: number; + }) { + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/A"].stateValues.xs.map((x) => x.tree)).eqls( + [x1, y1], + ); + expect(stateVariables["/B"].stateValues.xs.map((x) => x.tree)).eqls( + [x2, y2], + ); + + if ( + (propIndex === 1 || propIndex === 2) && + (componentIndex === 1 || componentIndex === 2) + ) { + let x: number; + if (propIndex === 1) { + if (componentIndex === 1) { + x = x1; + } else { + x = x2; + } + } else { + if (componentIndex === 1) { + x = y1; + } else { + x = y2; + } + } + + expect(stateVariables["/n1"].stateValues.value.tree).eq(x); + expect(stateVariables["/al2/n1"].stateValues.value.tree).eq(x); + } else if (force_values) { + expect(stateVariables["/n1"].stateValues.value.tree).eq( + "\uff3f", + ); + expect(stateVariables["/al2/n1"].stateValues.value.tree).eq( + "\uff3f", + ); + } else { + isUndefinedOrInactive(stateVariables["/n1"]); + isUndefinedOrInactive(stateVariables["/al2/n1"]); + } + } + + let x1 = 1, + y1 = 2, + x2 = 3, + y2 = 4; + + let componentIndex: undefined | number; + let propIndex: undefined | number; + + await check_items({ x1, y1, x2, y2, propIndex, componentIndex }); + + // set propIndex to 1 + propIndex = 1; + await updateMathInputValue({ + latex: "1", + componentName: "/n", + core, + }); + + await check_items({ x1, y1, x2, y2, propIndex, componentIndex }); + + // move point 1 + x1 = 9; + y1 = -5; + await core.requestAction({ + actionName: "movePoint", + componentName: "/A", + args: { x: x1, y: y1 }, + event: null, + }); + + await check_items({ x1, y1, x2, y2, propIndex, componentIndex }); + + // set componentIndex to 2 + componentIndex = 2; + await updateMathInputValue({ + latex: "2", + componentName: "/m", + core, + }); + + await check_items({ x1, y1, x2, y2, propIndex, componentIndex }); + + // move point2 + x2 = 0; + y2 = 8; + await core.requestAction({ + actionName: "movePoint", + componentName: "/B", + args: { x: x2, y: y2 }, + event: null, + }); + + await check_items({ x1, y1, x2, y2, propIndex, componentIndex }); + + // set propIndex to 2 + propIndex = 2; + await updateMathInputValue({ + latex: "2", + componentName: "/n", + core, + }); + await check_items({ x1, y1, x2, y2, propIndex, componentIndex }); + + // set componentIndex to 1 + componentIndex = 1; + await updateMathInputValue({ + latex: "1", + componentName: "/m", + core, + }); + await check_items({ x1, y1, x2, y2, propIndex, componentIndex }); + + // set propIndex to 3 + propIndex = 3; + await updateMathInputValue({ + latex: "3", + componentName: "/n", + core, + }); + await check_items({ x1, y1, x2, y2, propIndex, componentIndex }); + + // set propIndex to 1 + propIndex = 1; + await updateMathInputValue({ + latex: "1", + componentName: "/n", + core, + }); + await check_items({ x1, y1, x2, y2, propIndex, componentIndex }); + + // set componentIndex to 3 + componentIndex = 3; + await updateMathInputValue({ + latex: "3", + componentName: "/m", + core, + }); + await check_items({ x1, y1, x2, y2, propIndex, componentIndex }); + + // set componentIndex to 2 + componentIndex = 2; + await updateMathInputValue({ + latex: "2", + componentName: "/m", + core, + }); + + // clear propIndex + propIndex = undefined; + await updateMathInputValue({ + latex: "", + componentName: "/n", + core, + }); + await check_items({ x1, y1, x2, y2, propIndex, componentIndex }); + } + + it("copy propIndex and componentIndex, array notation, macros", async () => { + let core = await createTestCore({ + doenetML: ` +

m:

+

n:

+ + + (1,2) + (3,4) + + + + + + + +

$(col[$m].xs[$n]{assignNames="n1"})

+ +

$al{name="al2" newNamespace}

+ `, + }); + + await test_copy_prop_component_index(core, false); + }); + + it("copy propIndex and componentIndex, with copySource, array notation", async () => { + let core = await createTestCore({ + doenetML: ` +

m:

+

n:

+ + + (1,2) + (3,4) + + + + + + + +

+ +

+ + `, + }); + + await test_copy_prop_component_index(core, true); + }); + + it("source attributes to ignore", async () => { + let core = await createTestCore({ + doenetML: ` +

The text: secret

+ +

Text stays hidden by default:

+ $p1{name="p2"} +

Check attributes: $p2.hidden $p2.fixed $p2.isResponse $(p2/hidden.hidden) $(p2/hidden.fixed) $(p2/hidden.isResponse)

+ +

Now all is revealed:

+ +

Check attributes: $p5.hidden $p5.fixed $p5.isResponse $(p5/hidden.hidden) $(p5/hidden.fixed) $(p5/hidden.isResponse)

+ + `, + }); + + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq("The text: "); + expect(stateVariables["/p2"].stateValues.text).eq("The text: "); + expect(stateVariables["/p4"].stateValues.text).eq( + "Check attributes: false true false true true false", + ); + expect(stateVariables["/p5"].stateValues.text).eq("The text: secret"); + expect(stateVariables["/p7"].stateValues.text).eq( + "Check attributes: false false true false false true", + ); + }); + + it("copySource", async () => { + let core = await createTestCore({ + doenetML: ` + + (1,2) + + + + (3,4) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + `, + }); + + let P1 = [1, 2]; + let P2 = [3, 4]; + + let stateVariables = await returnAllStateVariables(core); + let g5PName = stateVariables["/g5"].activeChildren[0].componentName; + let g7PName = stateVariables["/g7"].activeChildren[0].componentName; + let g13PName = stateVariables["/g13"].activeChildren[0].componentName; + let g15PName = stateVariables["/g15"].activeChildren[0].componentName; + let g21PName = stateVariables["/g21"].activeChildren[0].componentName; + let g23PName = stateVariables["/g23"].activeChildren[0].componentName; + + expect(stateVariables["/P"].stateValues.xs.map((x) => x.tree)).eqls(P1); + expect(stateVariables["/g2/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables["/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g4/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + + expect(stateVariables[g5PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g6/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g7PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g8/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables["/g9/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g10/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g11/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g12/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + + expect(stateVariables[g13PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g14/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g15PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect( + stateVariables["/g16/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + expect(stateVariables["/g17/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g18/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g19/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g20/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + + expect(stateVariables[g21PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g22/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g23PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect( + stateVariables["/g24/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + expect(stateVariables["/g25/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g26/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g27/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g28/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + + // move P1 to (4,5) + + P1 = [4, 5]; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: P1[0], y: P1[1] }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/P"].stateValues.xs.map((x) => x.tree)).eqls(P1); + expect(stateVariables["/g2/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables["/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g4/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + + expect(stateVariables[g5PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g6/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g7PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g8/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables["/g9/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g10/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g11/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g12/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + + expect(stateVariables[g13PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g14/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g15PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect( + stateVariables["/g16/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + expect(stateVariables["/g17/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g18/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g19/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g20/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + + expect(stateVariables[g21PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g22/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g23PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect( + stateVariables["/g24/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + expect(stateVariables["/g25/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g26/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g27/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g28/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + + // move P2 to (7,0) + P2 = [7, 0]; + await core.requestAction({ + actionName: "movePoint", + componentName: "/g2/P", + args: { x: P2[0], y: P2[1] }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/P"].stateValues.xs.map((x) => x.tree)).eqls(P1); + expect(stateVariables["/g2/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables["/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g4/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + + expect(stateVariables[g5PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g6/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g7PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g8/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables["/g9/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g10/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g11/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g12/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + + expect(stateVariables[g13PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g14/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g15PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect( + stateVariables["/g16/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + expect(stateVariables["/g17/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g18/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g19/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g20/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + + expect(stateVariables[g21PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g22/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g23PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect( + stateVariables["/g24/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + expect(stateVariables["/g25/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g26/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g27/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g28/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + + // move P1 via Pa to (2,9) + P1 = [2, 0]; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/Pa", + args: { x: P1[0], y: P1[1] }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/P"].stateValues.xs.map((x) => x.tree)).eqls(P1); + expect(stateVariables["/g2/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables["/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g4/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + + expect(stateVariables[g5PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g6/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g7PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g8/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables["/g9/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g10/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g11/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g12/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + + expect(stateVariables[g13PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g14/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g15PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect( + stateVariables["/g16/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + expect(stateVariables["/g17/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g18/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g19/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g20/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + + expect(stateVariables[g21PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g22/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g23PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect( + stateVariables["/g24/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + expect(stateVariables["/g25/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g26/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g27/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g28/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + + // move P2 via graph 4's Pa to (8, 6) + P2 = [8, 6]; + await core.requestAction({ + actionName: "movePoint", + componentName: "/g4/Pa", + args: { x: P2[0], y: P2[1] }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/P"].stateValues.xs.map((x) => x.tree)).eqls(P1); + expect(stateVariables["/g2/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables["/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g4/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + + expect(stateVariables[g5PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g6/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g7PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g8/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables["/g9/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g10/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g11/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g12/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + + expect(stateVariables[g13PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g14/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g15PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect( + stateVariables["/g16/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + expect(stateVariables["/g17/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g18/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g19/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g20/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + + expect(stateVariables[g21PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g22/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g23PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect( + stateVariables["/g24/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + expect(stateVariables["/g25/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g26/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g27/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g28/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + }); + + it("copySource and copies with newNamespace", async () => { + let core = await createTestCore({ + doenetML: ` + + (1,2) + + $P.x{name="P1x"} + + (3,4) + + $(g2/P.x{name="P2x"}) + + + + + + + + + + + + $g1{name="g9" newNamespace} + $g2{name="g10" newNamespace} + $g3{name="g11" newNamespace} + $g4{name="g12" newNamespace} + + + + + + + + + + + $g5{name="g21" newNamespace} + $g6{name="g22" newNamespace} + $g7{name="g23" newNamespace} + $g8{name="g24" newNamespace} + $g9{name="g25" newNamespace} + $g10{name="g26" newNamespace} + $g11{name="g27" newNamespace} + $g12{name="g28" newNamespace} + + `, + }); + + let P1 = [1, 2]; + let P2 = [3, 4]; + + let stateVariables = await returnAllStateVariables(core); + let g5PName = stateVariables["/g5"].activeChildren[0].componentName; + let g7PName = stateVariables["/g7"].activeChildren[0].componentName; + let g13PName = stateVariables["/g13"].activeChildren[0].componentName; + let g15PName = stateVariables["/g15"].activeChildren[0].componentName; + let g21PName = stateVariables["/g21"].activeChildren[0].componentName; + let g23PName = stateVariables["/g23"].activeChildren[0].componentName; + + expect(stateVariables["/P"].stateValues.xs.map((x) => x.tree)).eqls(P1); + expect(stateVariables["/g2/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables["/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g4/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + + expect(stateVariables[g5PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g6/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g7PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g8/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables["/g9/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g10/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g11/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g12/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + + expect(stateVariables[g13PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g14/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g15PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect( + stateVariables["/g16/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + expect(stateVariables["/g17/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g18/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g19/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g20/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + + expect(stateVariables[g21PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g22/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g23PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect( + stateVariables["/g24/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + expect(stateVariables["/g25/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g26/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g27/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g28/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + + // move P1 to (4,5) + + P1 = [4, 5]; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: P1[0], y: P1[1] }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/P"].stateValues.xs.map((x) => x.tree)).eqls(P1); + expect(stateVariables["/g2/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables["/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g4/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + + expect(stateVariables[g5PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g6/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g7PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g8/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables["/g9/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g10/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g11/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g12/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + + expect(stateVariables[g13PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g14/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g15PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect( + stateVariables["/g16/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + expect(stateVariables["/g17/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g18/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g19/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g20/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + + expect(stateVariables[g21PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g22/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g23PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect( + stateVariables["/g24/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + expect(stateVariables["/g25/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g26/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g27/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g28/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + + // move P2 to (7,0) + + P2 = [7, 0]; + await core.requestAction({ + actionName: "movePoint", + componentName: "/g2/P", + args: { x: P2[0], y: P2[1] }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/P"].stateValues.xs.map((x) => x.tree)).eqls(P1); + expect(stateVariables["/g2/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables["/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g4/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + + expect(stateVariables[g5PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g6/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g7PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g8/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables["/g9/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g10/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g11/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g12/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + + expect(stateVariables[g13PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g14/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g15PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect( + stateVariables["/g16/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + expect(stateVariables["/g17/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g18/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g19/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g20/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + + expect(stateVariables[g21PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g22/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g23PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect( + stateVariables["/g24/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + expect(stateVariables["/g25/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g26/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g27/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g28/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + + // move P1 via Pa to (2,9) + + P1 = [2, 0]; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/Pa", + args: { x: P1[0], y: P1[1] }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/P"].stateValues.xs.map((x) => x.tree)).eqls(P1); + expect(stateVariables["/g2/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables["/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g4/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + + expect(stateVariables[g5PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g6/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g7PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g8/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables["/g9/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g10/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g11/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g12/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + + expect(stateVariables[g13PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g14/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g15PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect( + stateVariables["/g16/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + expect(stateVariables["/g17/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g18/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g19/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g20/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + + expect(stateVariables[g21PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g22/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g23PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect( + stateVariables["/g24/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + expect(stateVariables["/g25/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g26/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g27/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g28/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + + // move P2 via graph 4's Pa to (8, 6) + + P2 = [8, 6]; + await core.requestAction({ + actionName: "movePoint", + componentName: "/g4/Pa", + args: { x: P2[0], y: P2[1] }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/P"].stateValues.xs.map((x) => x.tree)).eqls(P1); + expect(stateVariables["/g2/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables["/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g4/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + + expect(stateVariables[g5PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g6/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g7PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g8/Pa"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables["/g9/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g10/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g11/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g12/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + + expect(stateVariables[g13PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g14/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g15PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect( + stateVariables["/g16/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + expect(stateVariables["/g17/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g18/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g19/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g20/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + + expect(stateVariables[g21PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g22/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect(stateVariables[g23PName].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect( + stateVariables["/g24/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + expect(stateVariables["/g25/P"].stateValues.xs.map((x) => x.tree)).eqls( + P1, + ); + expect(stateVariables["/g26/P"].stateValues.xs.map((x) => x.tree)).eqls( + P2, + ); + expect( + stateVariables["/g27/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P1); + expect( + stateVariables["/g28/Pa"].stateValues.xs.map((x) => x.tree), + ).eqls(P2); + }); + + async function test_copy_newNamespace_reference_parent(core) { + let stateVariables = await returnAllStateVariables(core); + + let mathinputoutsideName = + stateVariables["/answer1"].stateValues.inputChildren[0] + .componentName; + + let mathinputp1Name = + stateVariables["/answer2"].stateValues.inputChildren[0] + .componentName; + + let mathinputp2Name = + stateVariables["/p2/answer1"].stateValues.inputChildren[0] + .componentName; + + let mathinputp3Name = + stateVariables["/p3/answer2"].stateValues.inputChildren[0] + .componentName; + + let mathinputp4Name = + stateVariables["/p4/answer1"].stateValues.inputChildren[0] + .componentName; + + expect(stateVariables["/ca"].stateValues.value).eq(0); + expect(stateVariables["/p2/cao"].stateValues.value).eq(0); + expect(stateVariables["/p3/ca"].stateValues.value).eq(0); + expect(stateVariables["/p4/cao"].stateValues.value).eq(0); + + expect(stateVariables["/cao"].stateValues.value).eq(0); + expect(stateVariables["/p2/ca"].stateValues.value).eq(0); + expect(stateVariables["/p3/cao"].stateValues.value).eq(0); + expect(stateVariables["/p4/ca"].stateValues.value).eq(0); + + expect(stateVariables["/m"].stateValues.value.tree).eq("p"); + expect(stateVariables["/p2/m"].stateValues.value.tree).eq("p"); + expect(stateVariables["/p3/m"].stateValues.value.tree).eq("p"); + expect(stateVariables["/p4/m"].stateValues.value.tree).eq("p"); + + // answer outside answer + await updateMathInputValue({ + latex: "x", + componentName: mathinputoutsideName, + core, + }); + await core.requestAction({ + componentName: "/answer1", + actionName: "submitAnswer", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/answer1"].stateValues.justSubmitted).eq(true); + expect(stateVariables["/answer1"].stateValues.creditAchieved).eq(1); + expect(stateVariables["/answer2"].stateValues.justSubmitted).eq(false); + expect(stateVariables["/p2/answer1"].stateValues.justSubmitted).eq( + false, + ); + expect(stateVariables["/p3/answer2"].stateValues.justSubmitted).eq( + false, + ); + expect(stateVariables["/p4/answer1"].stateValues.justSubmitted).eq( + false, + ); + + // correctly answer first problem + await updateMathInputValue({ + latex: "y", + componentName: mathinputp1Name, + core, + }); + await core.requestAction({ + componentName: "/answer2", + actionName: "submitAnswer", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/answer1"].stateValues.justSubmitted).eq(true); + expect(stateVariables["/answer1"].stateValues.creditAchieved).eq(1); + expect(stateVariables["/answer2"].stateValues.justSubmitted).eq(true); + expect(stateVariables["/answer2"].stateValues.creditAchieved).eq(1); + expect(stateVariables["/p2/answer1"].stateValues.justSubmitted).eq( + false, + ); + expect(stateVariables["/p3/answer2"].stateValues.justSubmitted).eq( + true, + ); + expect(stateVariables["/p3/answer2"].stateValues.creditAchieved).eq(1); + expect(stateVariables["/p4/answer1"].stateValues.justSubmitted).eq( + false, + ); + + expect(stateVariables[mathinputp1Name].stateValues.rawRendererValue).eq( + "y", + ); + expect(stateVariables[mathinputp2Name].stateValues.rawRendererValue).eq( + "", + ); + expect(stateVariables[mathinputp3Name].stateValues.rawRendererValue).eq( + "y", + ); + expect(stateVariables[mathinputp4Name].stateValues.rawRendererValue).eq( + "", + ); + + expect(stateVariables["/ca"].stateValues.value).eq(1); + expect(stateVariables["/p2/cao"].stateValues.value).eq(1); + expect(stateVariables["/p3/ca"].stateValues.value).eq(1); + expect(stateVariables["/p4/cao"].stateValues.value).eq(1); + + expect(stateVariables["/cao"].stateValues.value).eq(0); + expect(stateVariables["/p2/ca"].stateValues.value).eq(0); + expect(stateVariables["/p3/cao"].stateValues.value).eq(0); + expect(stateVariables["/p4/ca"].stateValues.value).eq(0); + + expect(stateVariables["/m"].stateValues.value.tree).eq("p"); + expect(stateVariables["/p2/m"].stateValues.value.tree).eq("p"); + expect(stateVariables["/p3/m"].stateValues.value.tree).eq("p"); + expect(stateVariables["/p4/m"].stateValues.value.tree).eq("p"); + + // correctly answer second problem + await updateMathInputValue({ + latex: "z", + componentName: mathinputp2Name, + core, + }); + await core.requestAction({ + componentName: "/p2/answer1", + actionName: "submitAnswer", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/answer1"].stateValues.justSubmitted).eq(true); + expect(stateVariables["/answer1"].stateValues.creditAchieved).eq(1); + expect(stateVariables["/answer2"].stateValues.justSubmitted).eq(true); + expect(stateVariables["/answer2"].stateValues.creditAchieved).eq(1); + expect(stateVariables["/p2/answer1"].stateValues.justSubmitted).eq( + true, + ); + expect(stateVariables["/p2/answer1"].stateValues.creditAchieved).eq(1); + expect(stateVariables["/p3/answer2"].stateValues.justSubmitted).eq( + true, + ); + expect(stateVariables["/p3/answer2"].stateValues.creditAchieved).eq(1); + expect(stateVariables["/p4/answer1"].stateValues.justSubmitted).eq( + true, + ); + expect(stateVariables["/p4/answer1"].stateValues.creditAchieved).eq(1); + + expect(stateVariables[mathinputp1Name].stateValues.rawRendererValue).eq( + "y", + ); + expect(stateVariables[mathinputp2Name].stateValues.rawRendererValue).eq( + "z", + ); + expect(stateVariables[mathinputp3Name].stateValues.rawRendererValue).eq( + "y", + ); + expect(stateVariables[mathinputp4Name].stateValues.rawRendererValue).eq( + "z", + ); + + expect(stateVariables["/ca"].stateValues.value).eq(1); + expect(stateVariables["/p2/cao"].stateValues.value).eq(1); + expect(stateVariables["/p3/ca"].stateValues.value).eq(1); + expect(stateVariables["/p4/cao"].stateValues.value).eq(1); + + expect(stateVariables["/cao"].stateValues.value).eq(1); + expect(stateVariables["/p2/ca"].stateValues.value).eq(1); + expect(stateVariables["/p3/cao"].stateValues.value).eq(1); + expect(stateVariables["/p4/ca"].stateValues.value).eq(1); + + expect(stateVariables["/m"].stateValues.value.tree).eq("p"); + expect(stateVariables["/p2/m"].stateValues.value.tree).eq("p"); + expect(stateVariables["/p3/m"].stateValues.value.tree).eq("p"); + expect(stateVariables["/p4/m"].stateValues.value.tree).eq("p"); + + // incorrectly answer third problem + await updateMathInputValue({ + latex: "a", + componentName: mathinputp3Name, + core, + }); + await core.requestAction({ + componentName: "/p3/answer2", + actionName: "submitAnswer", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/answer1"].stateValues.justSubmitted).eq(true); + expect(stateVariables["/answer1"].stateValues.creditAchieved).eq(1); + expect(stateVariables["/answer2"].stateValues.justSubmitted).eq(true); + expect(stateVariables["/answer2"].stateValues.creditAchieved).eq(0); + expect(stateVariables["/p2/answer1"].stateValues.justSubmitted).eq( + true, + ); + expect(stateVariables["/p2/answer1"].stateValues.creditAchieved).eq(1); + expect(stateVariables["/p3/answer2"].stateValues.justSubmitted).eq( + true, + ); + expect(stateVariables["/p3/answer2"].stateValues.creditAchieved).eq(0); + expect(stateVariables["/p4/answer1"].stateValues.justSubmitted).eq( + true, + ); + expect(stateVariables["/p4/answer1"].stateValues.creditAchieved).eq(1); + + expect(stateVariables[mathinputp1Name].stateValues.rawRendererValue).eq( + "a", + ); + expect(stateVariables[mathinputp2Name].stateValues.rawRendererValue).eq( + "z", + ); + expect(stateVariables[mathinputp3Name].stateValues.rawRendererValue).eq( + "a", + ); + expect(stateVariables[mathinputp4Name].stateValues.rawRendererValue).eq( + "z", + ); + + expect(stateVariables["/ca"].stateValues.value).eq(0); + expect(stateVariables["/p2/cao"].stateValues.value).eq(0); + expect(stateVariables["/p3/ca"].stateValues.value).eq(0); + expect(stateVariables["/p4/cao"].stateValues.value).eq(0); + + expect(stateVariables["/cao"].stateValues.value).eq(1); + expect(stateVariables["/p2/ca"].stateValues.value).eq(1); + expect(stateVariables["/p3/cao"].stateValues.value).eq(1); + expect(stateVariables["/p4/ca"].stateValues.value).eq(1); + + expect(stateVariables["/m"].stateValues.value.tree).eq("p"); + expect(stateVariables["/p2/m"].stateValues.value.tree).eq("p"); + expect(stateVariables["/p3/m"].stateValues.value.tree).eq("p"); + expect(stateVariables["/p4/m"].stateValues.value.tree).eq("p"); + + // incorrectly answer fourth problem + await updateMathInputValue({ + latex: "b", + componentName: mathinputp4Name, + core, + }); + await core.requestAction({ + componentName: "/p4/answer1", + actionName: "submitAnswer", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/answer1"].stateValues.justSubmitted).eq(true); + expect(stateVariables["/answer1"].stateValues.creditAchieved).eq(1); + expect(stateVariables["/answer2"].stateValues.justSubmitted).eq(true); + expect(stateVariables["/answer2"].stateValues.creditAchieved).eq(0); + expect(stateVariables["/p2/answer1"].stateValues.justSubmitted).eq( + true, + ); + expect(stateVariables["/p2/answer1"].stateValues.creditAchieved).eq(0); + expect(stateVariables["/p3/answer2"].stateValues.justSubmitted).eq( + true, + ); + expect(stateVariables["/p3/answer2"].stateValues.creditAchieved).eq(0); + expect(stateVariables["/p4/answer1"].stateValues.justSubmitted).eq( + true, + ); + expect(stateVariables["/p4/answer1"].stateValues.creditAchieved).eq(0); + + expect(stateVariables[mathinputp1Name].stateValues.rawRendererValue).eq( + "a", + ); + expect(stateVariables[mathinputp2Name].stateValues.rawRendererValue).eq( + "b", + ); + expect(stateVariables[mathinputp3Name].stateValues.rawRendererValue).eq( + "a", + ); + expect(stateVariables[mathinputp4Name].stateValues.rawRendererValue).eq( + "b", + ); + + expect(stateVariables["/ca"].stateValues.value).eq(0); + expect(stateVariables["/p2/cao"].stateValues.value).eq(0); + expect(stateVariables["/p3/ca"].stateValues.value).eq(0); + expect(stateVariables["/p4/cao"].stateValues.value).eq(0); + + expect(stateVariables["/cao"].stateValues.value).eq(0); + expect(stateVariables["/p2/ca"].stateValues.value).eq(0); + expect(stateVariables["/p3/cao"].stateValues.value).eq(0); + expect(stateVariables["/p4/ca"].stateValues.value).eq(0); + + expect(stateVariables["/m"].stateValues.value.tree).eq("p"); + expect(stateVariables["/p2/m"].stateValues.value.tree).eq("p"); + expect(stateVariables["/p3/m"].stateValues.value.tree).eq("p"); + expect(stateVariables["/p4/m"].stateValues.value.tree).eq("p"); + + // change mathinput + + await updateMathInputValue({ + latex: "q", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m"].stateValues.value.tree).eq("q"); + expect(stateVariables["/p2/m"].stateValues.value.tree).eq("q"); + expect(stateVariables["/p3/m"].stateValues.value.tree).eq("q"); + expect(stateVariables["/p4/m"].stateValues.value.tree).eq("q"); + } + + it("copy with newNamespace and references to parent", async () => { + let core = await createTestCore({ + doenetML: ` + + x + + + y +

Credit achieved: $p1.creditAchieved{assignNames="ca"}

+

Value of mathinput: $mi.value{assignNames="m"}

+

Other answer credit achieved: $(p2/answer1.creditAchieved{assignNames="cao"})

+
+ + + z +

Credit achieved: $(../p2.creditAchieved{assignNames="ca"})

+

Value of mathinput: $(../mi.value{assignNames="m"})

+

Other answer credit achieved: $(../answer2.creditAchieved{assignNames="cao"})

+
+ + $p1{name="p3" newNamespace} + + $p2{name="p4" newNamespace} + + `, + }); + + await test_copy_newNamespace_reference_parent(core); + }); + + it("copySource with newNamespace and references to parent", async () => { + let core = await createTestCore({ + doenetML: ` + + x + + + y +

Credit achieved:

+

Value of mathinput:

+

Other answer credit achieved:

+
+ + + z +

Credit achieved:

+

Value of mathinput:

+

Other answer credit achieved:

+
+ + + + + + `, + }); + + await test_copy_newNamespace_reference_parent(core); + }); + + async function test_copy_map(core) { + async function check_items({ + n, + x = "\uff3f", + y = "\uff3f", + z = "\uff3f", + }: { + n: number; + x?: string; + y?: string; + z?: string; + }) { + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n2"].stateValues.value.tree).eq(n); + expect(stateVariables["/n3"].stateValues.value).eq(n); + + expect(stateVariables["/p1"].stateValues.text).contain("Hello 1!"); + expect(stateVariables["/p2"].stateValues.text).contain("Hello 2!"); + expect(stateVariables["/p1a"].stateValues.text).contain("Hello 1!"); + expect(stateVariables["/p2a"].stateValues.text).contain("Hello 2!"); + expect(stateVariables["/p1b"].stateValues.text).contain("Hello 1!"); + expect(stateVariables["/p2b"].stateValues.text).contain("Hello 2!"); + if (n === 3) { + expect(stateVariables["/p3"].stateValues.text).contain( + "Hello 3!", + ); + expect(stateVariables["/p3a"].stateValues.text).contain( + "Hello 3!", + ); + expect(stateVariables["/p3b"].stateValues.text).contain( + "Hello 3!", + ); + } else { + expect(stateVariables["/p3"]).eq(undefined); + expect(stateVariables["/p3a"]).eq(undefined); + expect(stateVariables["/p3b"]).eq(undefined); + } + + expect(stateVariables["/p1/n1"].stateValues.value).eq(1); + expect(stateVariables["/p2/n1"].stateValues.value).eq(2); + expect(stateVariables["/p1a/n1"].stateValues.value).eq(1); + expect(stateVariables["/p2a/n1"].stateValues.value).eq(2); + expect(stateVariables["/p1b/n1"].stateValues.value).eq(1); + expect(stateVariables["/p2b/n1"].stateValues.value).eq(2); + if (n === 3) { + expect(stateVariables["/p3/n1"].stateValues.value).eq(3); + expect(stateVariables["/p3a/n1"].stateValues.value).eq(3); + expect(stateVariables["/p3b/n1"].stateValues.value).eq(3); + } else { + expect(stateVariables["/p3/n1"]).eq(undefined); + expect(stateVariables["/p3a/n1"]).eq(undefined); + expect(stateVariables["/p3b/n1"]).eq(undefined); + } + + expect(stateVariables["/p1/m1"].stateValues.value.tree).eq(x); + expect(stateVariables["/p2/m1"].stateValues.value.tree).eq(y); + expect(stateVariables["/p1a/m1"].stateValues.value.tree).eq(x); + expect(stateVariables["/p2a/m1"].stateValues.value.tree).eq(y); + expect(stateVariables["/p1b/m1"].stateValues.value.tree).eq(x); + expect(stateVariables["/p2b/m1"].stateValues.value.tree).eq(y); + if (n === 3) { + expect(stateVariables["/p3/m1"].stateValues.value.tree).eq(z); + expect(stateVariables["/p3a/m1"].stateValues.value.tree).eq(z); + expect(stateVariables["/p3b/m1"].stateValues.value.tree).eq(z); + } else { + expect(stateVariables["/p3/m1"]).eq(undefined); + expect(stateVariables["/p3a/m1"]).eq(undefined); + expect(stateVariables["/p3b/m1"]).eq(undefined); + } + } + + await check_items({ n: 2 }); + + // type x in first mathinput + await updateMathInputValue({ + latex: "x", + componentName: "/p1/x", + core, + }); + + await check_items({ n: 2, x: "x" }); + + // type y in second mathinput + await updateMathInputValue({ + latex: "y", + componentName: "/p2b/x", + core, + }); + + await check_items({ n: 2, x: "x", y: "y" }); + + // increase n + await updateMathInputValue({ + latex: "3", + componentName: "/n", + core, + }); + + await check_items({ n: 3, x: "x", y: "y" }); + + // type z in third mathinput + await updateMathInputValue({ + latex: "z", + componentName: "/p3a/x", + core, + }); + + await check_items({ n: 3, x: "x", y: "y", z: "z" }); + } + + it("copySource of map", async () => { + let core = await createTestCore({ + doenetML: ` + + +

Value:

+

Value 2:

+ + + + + + + + + + + + `, + }); + + await test_copy_map(core); + }); + + it("macro to copy map", async () => { + let core = await createTestCore({ + doenetML: ` + a + + + +

Value: $n.value{assignNames="n2"}

+

Value 2: $n2{name="n3" createComponentOfType="number"}

+ + + + + + + $map1{name="map2" assignNames="(p1a) (p2a) (p3a)"} + + $map2{name="map3" assignNames="(p1b) (p2b) (p3b)"} + + + `, + }); + + await test_copy_map(core); + }); + + it("copySource and createComponentOfType wrap to match specified type", async () => { + let core = await createTestCore({ + doenetML: ` + + + + $mi{name="m2" createComponentOfType="MatH"} + + + $mi{name="n2" createComponentOfType="number"} + + (x,y) + + + $P{name="c2" createComponentOfType="coords"} + + $P.coords{assignNames="c4" createComponentOfType="coords"} + + + $P{name="mc2" createComponentOfType="math"} + + $P.coords{assignNames="mc4" createComponentOfType="math"} + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/m1"].stateValues.value.tree).eq(2); + expect(stateVariables["/m2"].stateValues.value.tree).eq(2); + + expect(stateVariables["/n1"].stateValues.value).eq(2); + expect(stateVariables["/n2"].stateValues.value).eq(2); + + expect(stateVariables["/c1"].stateValues.value.tree).eqls([ + "vector", + "x", + "y", + ]); + expect(stateVariables["/c2"].stateValues.value.tree).eqls([ + "vector", + "x", + "y", + ]); + expect(stateVariables["/c3"].stateValues.value.tree).eqls([ + "vector", + "x", + "y", + ]); + expect(stateVariables["/c4"].stateValues.value.tree).eqls([ + "vector", + "x", + "y", + ]); + + expect(stateVariables["/mc1"].stateValues.value.tree).eqls([ + "vector", + "x", + "y", + ]); + expect(stateVariables["/mc2"].stateValues.value.tree).eqls([ + "vector", + "x", + "y", + ]); + expect(stateVariables["/mc3"].stateValues.value.tree).eqls([ + "vector", + "x", + "y", + ]); + expect(stateVariables["/mc4"].stateValues.value.tree).eqls([ + "vector", + "x", + "y", + ]); + + // enter a + await updateMathInputValue({ latex: "a", componentName: "/mi", core }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/m1"].stateValues.value.tree).eq("a"); + expect(stateVariables["/m2"].stateValues.value.tree).eq("a"); + + expect(stateVariables["/n1"].stateValues.value).eqls(NaN); + expect(stateVariables["/n2"].stateValues.value).eqls(NaN); + }); + + it("add children to invalid copySource", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/g"].activeChildren.length).eq(1); + expect(stateVariables["/g"].activeChildren[0].componentName).eq("/P"); + expect(stateVariables["/P"].stateValues.xs.map((x) => x.tree)).eqls([ + 0, 0, + ]); + + expect(stateVariables["/g2"].activeChildren.length).eq(1); + expect(stateVariables["/g2"].activeChildren[0].componentName).eq( + "/g2/P", + ); + expect(stateVariables["/g2/P"].stateValues.xs.map((x) => x.tree)).eqls([ + 0, 0, + ]); + + expect(stateVariables["/Pcoords"].stateValues.value.tree).eqls([ + "vector", + 0, + 0, + ]); + expect(stateVariables["/g2Pcoords"].stateValues.value.tree).eqls([ + "vector", + 0, + 0, + ]); + + // move points + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 3, y: 5 }, + event: null, + }); + await core.requestAction({ + actionName: "movePoint", + componentName: "/g2/P", + args: { x: 7, y: 6 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/P"].stateValues.xs.map((x) => x.tree)).eqls([ + 3, 5, + ]); + + expect(stateVariables["/g2/P"].stateValues.xs.map((x) => x.tree)).eqls([ + 7, 6, + ]); + + expect(stateVariables["/Pcoords"].stateValues.value.tree).eqls([ + "vector", + 3, + 5, + ]); + expect(stateVariables["/g2Pcoords"].stateValues.value.tree).eqls([ + "vector", + 7, + 6, + ]); + }); + + it("add children with copySource, different newNamespace combinations", async () => { + let core = await createTestCore({ + doenetML: ` + + (1,2) + + + + (4,5) + + + + + + + (1,2) + + + + (4,5) + + + + + + + + (1,2) + + + + (4,5) + + + + + + + + (1,2) + + + + (4,5) + + + + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/g1"].activeChildren.length).eq(1); + expect(stateVariables["/g1"].activeChildren[0].componentName).eq("/P1"); + expect(stateVariables["/P1"].stateValues.xs.map((x) => x.tree)).eqls([ + 1, 2, + ]); + expect(stateVariables["/g1a"].activeChildren.length).eq(2); + expect(stateVariables["/g1a"].activeChildren[1].componentName).eq( + "/v1", + ); + let P1aName = stateVariables["/g1a"].activeChildren[0].componentName; + expect(stateVariables[P1aName].stateValues.xs.map((x) => x.tree)).eqls([ + 1, 2, + ]); + expect( + stateVariables["/v1"].stateValues.displacement.map((x) => x.tree), + ).eqls([4, 5]); + expect(stateVariables["/P1coords"].stateValues.value.tree).eqls([ + "vector", + 1, + 2, + ]); + expect(stateVariables["/v1displacement"].stateValues.value.tree).eqls([ + "vector", + 4, + 5, + ]); + + expect(stateVariables["/g2"].activeChildren.length).eq(1); + expect(stateVariables["/g2"].activeChildren[0].componentName).eq("/P2"); + expect(stateVariables["/P2"].stateValues.xs.map((x) => x.tree)).eqls([ + 1, 2, + ]); + expect(stateVariables["/g2a"].activeChildren.length).eq(2); + expect(stateVariables["/g2a"].activeChildren[0].componentName).eq( + "/g2a/P2", + ); + expect(stateVariables["/g2a"].activeChildren[1].componentName).eq( + "/g2a/v2", + ); + expect( + stateVariables["/g2a/P2"].stateValues.xs.map((x) => x.tree), + ).eqls([1, 2]); + expect( + stateVariables["/g2a/v2"].stateValues.displacement.map( + (x) => x.tree, + ), + ).eqls([4, 5]); + expect(stateVariables["/P2coords"].stateValues.value.tree).eqls([ + "vector", + 1, + 2, + ]); + expect(stateVariables["/P2acoords"].stateValues.value.tree).eqls([ + "vector", + 1, + 2, + ]); + expect(stateVariables["/v2displacement"].stateValues.value.tree).eqls([ + "vector", + 4, + 5, + ]); + + expect(stateVariables["/g3"].activeChildren.length).eq(1); + expect(stateVariables["/g3"].activeChildren[0].componentName).eq( + "/g3/P3", + ); + expect(stateVariables["/g3/P3"].stateValues.xs.map((x) => x.tree)).eqls( + [1, 2], + ); + expect(stateVariables["/g3a"].activeChildren.length).eq(2); + expect(stateVariables["/g3a"].activeChildren[0].componentName).eq( + "/g3a/P3", + ); + expect(stateVariables["/g3a"].activeChildren[1].componentName).eq( + "/g3a/v3", + ); + expect( + stateVariables["/g3a/P3"].stateValues.xs.map((x) => x.tree), + ).eqls([1, 2]); + expect( + stateVariables["/g3a/v3"].stateValues.displacement.map( + (x) => x.tree, + ), + ).eqls([4, 5]); + expect(stateVariables["/P3coords"].stateValues.value.tree).eqls([ + "vector", + 1, + 2, + ]); + expect(stateVariables["/P3acoords"].stateValues.value.tree).eqls([ + "vector", + 1, + 2, + ]); + expect(stateVariables["/v3displacement"].stateValues.value.tree).eqls([ + "vector", + 4, + 5, + ]); + + expect(stateVariables["/g4"].activeChildren.length).eq(1); + expect(stateVariables["/g4"].activeChildren[0].componentName).eq( + "/g4/P4", + ); + expect(stateVariables["/g4/P4"].stateValues.xs.map((x) => x.tree)).eqls( + [1, 2], + ); + expect(stateVariables["/g4a"].activeChildren.length).eq(2); + expect(stateVariables["/g4a"].activeChildren[0].componentName).eq( + "/g4a/P4", + ); + expect(stateVariables["/g4a"].activeChildren[1].componentName).eq( + "/v4", + ); + expect( + stateVariables["/g4a/P4"].stateValues.xs.map((x) => x.tree), + ).eqls([1, 2]); + expect( + stateVariables["/v4"].stateValues.displacement.map((x) => x.tree), + ).eqls([4, 5]); + expect(stateVariables["/P4coords"].stateValues.value.tree).eqls([ + "vector", + 1, + 2, + ]); + expect(stateVariables["/P4acoords"].stateValues.value.tree).eqls([ + "vector", + 1, + 2, + ]); + expect(stateVariables["/v4displacement"].stateValues.value.tree).eqls([ + "vector", + 4, + 5, + ]); + + // move points + + await core.requestAction({ + event: null, + actionName: "movePoint", + componentName: "/P1", + args: { x: 3, y: 5 }, + }); + await core.requestAction({ + event: null, + actionName: "moveVector", + componentName: "/v1", + args: { + headcoords: [8, 7], + }, + }); + await core.requestAction({ + event: null, + actionName: "movePoint", + componentName: "/P2", + args: { x: 6, y: 0 }, + }); + await core.requestAction({ + event: null, + actionName: "moveVector", + componentName: "/g2a/v2", + args: { + headcoords: [9, 1], + }, + }); + await core.requestAction({ + event: null, + actionName: "movePoint", + componentName: "/g3/P3", + args: { x: 5, y: 8 }, + }); + await core.requestAction({ + event: null, + actionName: "moveVector", + componentName: "/g3a/v3", + args: { + headcoords: [8, 6], + }, + }); + await core.requestAction({ + event: null, + actionName: "movePoint", + componentName: "/g4/P4", + args: { x: 0, y: 3 }, + }); + await core.requestAction({ + event: null, + actionName: "moveVector", + componentName: "/v4", + args: { + headcoords: [7, 2], + }, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/P1"].stateValues.xs.map((x) => x.tree)).eqls([ + 3, 5, + ]); + expect(stateVariables[P1aName].stateValues.xs.map((x) => x.tree)).eqls([ + 3, 5, + ]); + expect( + stateVariables["/v1"].stateValues.displacement.map((x) => x.tree), + ).eqls([8, 7]); + expect(stateVariables["/P1coords"].stateValues.value.tree).eqls([ + "vector", + 3, + 5, + ]); + expect(stateVariables["/v1displacement"].stateValues.value.tree).eqls([ + "vector", + 8, + 7, + ]); + + expect(stateVariables["/P2"].stateValues.xs.map((x) => x.tree)).eqls([ + 6, 0, + ]); + expect( + stateVariables["/g2a/P2"].stateValues.xs.map((x) => x.tree), + ).eqls([6, 0]); + expect( + stateVariables["/g2a/v2"].stateValues.displacement.map( + (x) => x.tree, + ), + ).eqls([9, 1]); + expect(stateVariables["/P2coords"].stateValues.value.tree).eqls([ + "vector", + 6, + 0, + ]); + expect(stateVariables["/P2acoords"].stateValues.value.tree).eqls([ + "vector", + 6, + 0, + ]); + expect(stateVariables["/v2displacement"].stateValues.value.tree).eqls([ + "vector", + 9, + 1, + ]); + + expect(stateVariables["/g3/P3"].stateValues.xs.map((x) => x.tree)).eqls( + [5, 8], + ); + expect( + stateVariables["/g3a/P3"].stateValues.xs.map((x) => x.tree), + ).eqls([5, 8]); + expect( + stateVariables["/g3a/v3"].stateValues.displacement.map( + (x) => x.tree, + ), + ).eqls([8, 6]); + expect(stateVariables["/P3coords"].stateValues.value.tree).eqls([ + "vector", + 5, + 8, + ]); + expect(stateVariables["/P3acoords"].stateValues.value.tree).eqls([ + "vector", + 5, + 8, + ]); + expect(stateVariables["/v3displacement"].stateValues.value.tree).eqls([ + "vector", + 8, + 6, + ]); + + expect(stateVariables["/g4/P4"].stateValues.xs.map((x) => x.tree)).eqls( + [0, 3], + ); + expect( + stateVariables["/g4a/P4"].stateValues.xs.map((x) => x.tree), + ).eqls([0, 3]); + expect( + stateVariables["/v4"].stateValues.displacement.map((x) => x.tree), + ).eqls([7, 2]); + expect(stateVariables["/P4coords"].stateValues.value.tree).eqls([ + "vector", + 0, + 3, + ]); + expect(stateVariables["/P4acoords"].stateValues.value.tree).eqls([ + "vector", + 0, + 3, + ]); + expect(stateVariables["/v4displacement"].stateValues.value.tree).eqls([ + "vector", + 7, + 2, + ]); + + // move shadowed points + + await core.requestAction({ + event: null, + actionName: "movePoint", + componentName: P1aName, + args: { x: 2, y: 1 }, + }); + await core.requestAction({ + event: null, + actionName: "movePoint", + componentName: "/g2a/P2", + args: { x: 5, y: 4 }, + }); + await core.requestAction({ + event: null, + actionName: "movePoint", + componentName: "/g3a/P3", + args: { x: 9, y: 7 }, + }); + await core.requestAction({ + event: null, + actionName: "movePoint", + componentName: "/g4a/P4", + args: { x: 7, y: 6 }, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/P1"].stateValues.xs.map((x) => x.tree)).eqls([ + 2, 1, + ]); + expect(stateVariables[P1aName].stateValues.xs.map((x) => x.tree)).eqls([ + 2, 1, + ]); + expect( + stateVariables["/v1"].stateValues.displacement.map((x) => x.tree), + ).eqls([8, 7]); + expect(stateVariables["/P1coords"].stateValues.value.tree).eqls([ + "vector", + 2, + 1, + ]); + expect(stateVariables["/v1displacement"].stateValues.value.tree).eqls([ + "vector", + 8, + 7, + ]); + + expect(stateVariables["/P2"].stateValues.xs.map((x) => x.tree)).eqls([ + 5, 4, + ]); + expect( + stateVariables["/g2a/P2"].stateValues.xs.map((x) => x.tree), + ).eqls([5, 4]); + expect( + stateVariables["/g2a/v2"].stateValues.displacement.map( + (x) => x.tree, + ), + ).eqls([9, 1]); + expect(stateVariables["/P2coords"].stateValues.value.tree).eqls([ + "vector", + 5, + 4, + ]); + expect(stateVariables["/P2acoords"].stateValues.value.tree).eqls([ + "vector", + 5, + 4, + ]); + expect(stateVariables["/v2displacement"].stateValues.value.tree).eqls([ + "vector", + 9, + 1, + ]); + + expect(stateVariables["/g3/P3"].stateValues.xs.map((x) => x.tree)).eqls( + [9, 7], + ); + expect( + stateVariables["/g3a/P3"].stateValues.xs.map((x) => x.tree), + ).eqls([9, 7]); + expect( + stateVariables["/g3a/v3"].stateValues.displacement.map( + (x) => x.tree, + ), + ).eqls([8, 6]); + expect(stateVariables["/P3coords"].stateValues.value.tree).eqls([ + "vector", + 9, + 7, + ]); + expect(stateVariables["/P3acoords"].stateValues.value.tree).eqls([ + "vector", + 9, + 7, + ]); + expect(stateVariables["/v3displacement"].stateValues.value.tree).eqls([ + "vector", + 8, + 6, + ]); + + expect(stateVariables["/g4/P4"].stateValues.xs.map((x) => x.tree)).eqls( + [7, 6], + ); + expect( + stateVariables["/g4a/P4"].stateValues.xs.map((x) => x.tree), + ).eqls([7, 6]); + expect( + stateVariables["/v4"].stateValues.displacement.map((x) => x.tree), + ).eqls([7, 2]); + expect(stateVariables["/P4coords"].stateValues.value.tree).eqls([ + "vector", + 7, + 6, + ]); + expect(stateVariables["/P4acoords"].stateValues.value.tree).eqls([ + "vector", + 7, + 6, + ]); + expect(stateVariables["/v4displacement"].stateValues.value.tree).eqls([ + "vector", + 7, + 2, + ]); + }); + + it("add children with copySource, ignore implicit newNamespace when copied", async () => { + let core = await createTestCore({ + doenetML: ` + + + (1,2) + + + + + + + + + + + + + + +

Point 1:

+

Point 2:

+

Vector 2:

+

Point 3:

+

Vector 3:

+

Point 4:

+

Nothing at g4/v:

+ + +

Grp2 Point 1:

+

Grp2 Point 2:

+ +

Grp2 Vector 2:

+

Nothing at /grp2/g2/v:

+ +

Grp2 Point 3:

+

Grp2 Vector 3:

+ +

Grp2 Point 4:

+

Nothing at /grp2/g4/v:

+
+ + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + const coordsNames = [ + "/P1coords", + "/P2coords", + "/P3coords", + "/P4coords", + "/grp2ps/P1coords", + "/grp2ps/P2coords", + "/grp2ps/P3coords", + "/grp2ps/P4coords", + ]; + + for (let name of coordsNames) { + expect(stateVariables[name].stateValues.value.tree).eqls([ + "vector", + 1, + 2, + ]); + } + + const displacementNames = [ + "/v2displacement", + "/v3displacement", + "/grp2ps/v2displacement", + "/grp2ps/v3displacement", + ]; + for (let name of displacementNames) { + expect(stateVariables[name].stateValues.value.tree).eqls([ + "vector", + 1, + 0, + ]); + } + + const noDisplacementNames = [ + "/v4nodisplacement", + "/grp2ps/v2nodisplacement", + "/grp2ps/v4nodisplacement", + ]; + for (let name of noDisplacementNames) { + expect(stateVariables[name].stateValues.value.tree).eqls("\uff3f"); + } + + expect(stateVariables["/g/P"].stateValues.xs.map((x) => x.tree)).eqls([ + 1, 2, + ]); + expect(stateVariables["/g2/P"].stateValues.xs.map((x) => x.tree)).eqls([ + 1, 2, + ]); + expect( + stateVariables["/v"].stateValues.displacement.map((x) => x.tree), + ).eqls([1, 0]); + expect(stateVariables["/g3/P"].stateValues.xs.map((x) => x.tree)).eqls([ + 1, 2, + ]); + expect( + stateVariables["/g3/v"].stateValues.displacement.map((x) => x.tree), + ).eqls([1, 0]); + expect(stateVariables["/g4/P"].stateValues.xs.map((x) => x.tree)).eqls([ + 1, 2, + ]); + let g4vName = stateVariables["/g4"].activeChildren[1].componentName; + expect(g4vName.substring(0, 3) === "/__"); + expect( + stateVariables[g4vName].stateValues.displacement.map((x) => x.tree), + ).eqls([1, 0]); + expect(stateVariables["/g4/v"]).eq(undefined); + + expect( + stateVariables["/grp2/g/P"].stateValues.xs.map((x) => x.tree), + ).eqls([1, 2]); + expect( + stateVariables["/grp2/g2/P"].stateValues.xs.map((x) => x.tree), + ).eqls([1, 2]); + expect( + stateVariables["/grp2/v"].stateValues.displacement.map( + (x) => x.tree, + ), + ).eqls([1, 0]); + expect(stateVariables["/grp2/g2/v"]).eq(undefined); + expect( + stateVariables["/grp2/g3/P"].stateValues.xs.map((x) => x.tree), + ).eqls([1, 2]); + expect( + stateVariables["/grp2/g3/v"].stateValues.displacement.map( + (x) => x.tree, + ), + ).eqls([1, 0]); + expect( + stateVariables["/grp2/g4/P"].stateValues.xs.map((x) => x.tree), + ).eqls([1, 2]); + let grp2g4vName = + stateVariables["/grp2/g4"].activeChildren[1].componentName; + expect(grp2g4vName.substring(0, 3) === "/__"); + expect( + stateVariables[grp2g4vName].stateValues.displacement.map( + (x) => x.tree, + ), + ).eqls([1, 0]); + expect(stateVariables["/grp2/g4/v"]).eq(undefined); + }); + + it("add children with copySource, multiple levels of groups", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + (1,2) + + + + (4,5) + + + + + + + + $g{name="g4"} + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Point 1:

+

Point 2:

+

Vector 2:

+

Point 3:

+

Vector 3:

+

Circle 3 center:

+

Line segment 3 point 1:

+

Line segment 3 point 2:

+

Point 4:

+

Point 5:

+

Circle 5 center:

+ + +

Grp2 Point 1:

+

Grp2 Point 2:

+

Grp2 Vector 2:

+

Grp2 Point 3:

+

Grp2 Vector 3:

+

Grp2 Circle 3 center:

+

Grp2 Line segment 3 point 1:

+

Grp2 Line segment 3 point 2:

+

Grp2 Point 4:

+

Grp2 Point 5:

+

Grp2 Circle 5 center:

+

Grp2 Point 6:

+

Grp2 Circle 6 center:

+

Grp2 Line segment 6 point 1:

+

Grp2 Line segment 6 point 2:

+
+ + + + +

Grp3 Point 1:

+

Grp3 Point 2:

+

Grp3 Vector 2:

+

Grp3 Point 3:

+

Grp3 Vector 3:

+

Grp3 Circle 3 center:

+

Grp3 Line segment 3 point 1:

+

Grp3 Line segment 3 point 2:

+

Grp3 Point 4:

+

Grp3 Point 5:

+

Grp3 Circle 5 center:

+ + +

Grp3 Grp2 Point 1:

+

Grp3 Grp2 Point 2:

+

Grp3 Grp2 Vector 2:

+

Grp3 Grp2 Point 3:

+

Grp3 Grp2 Vector 3:

+

Grp3 Grp2 Circle 3 center:

+

Grp3 Grp2 Line segment 3 point 1:

+

Grp3 Grp2 Line segment 3 point 2:

+

Grp3 Grp2 Point 4:

+

Grp3 Grp2 Point 5:

+

Grp3 Grp2 Circle 5 center:

+

Grp3 Grp2 Point 6:

+

Grp3 Grp2 Circle 6 center:

+

Grp3 Grp2 Line segment 6 point 1:

+

Grp3 Grp2 Line segment 6 point 2:

+

Grp3 Point 7:

+

Grp3 Circle 7 center:

+

Grp3 Line segment 7 point 1:

+

Grp3 Line segment 7 point 2:

+

Grp3 Vector 7 head:

+

Grp3 Vector 7 tail:

+
+ +
+ + + + `, + }); + + async function check_items({ + P, + v, + vH, + c0, + }: { + P: number[]; + v: number[]; + vH: number[]; + c0: number[]; + }) { + const stateVariables = await returnAllStateVariables(core); + + const coordsNames = [ + "/P1coords", + "/P2coords", + "/P3coords", + "/P4coords", + "/P5coords", + "/grp2ps/P1coords", + "/grp2ps/P2coords", + "/grp2ps/P3coords", + "/grp2ps/P4coords", + "/grp2ps/P5coords", + "/grp2ps/P6coords", + "/grp3ps/P1coords", + "/grp3ps/P2coords", + "/grp3ps/P3coords", + "/grp3ps/P4coords", + "/grp3ps/P5coords", + "/grp3ps/grp2ps/P1coords", + "/grp3ps/grp2ps/P2coords", + "/grp3ps/grp2ps/P3coords", + "/grp3ps/grp2ps/P4coords", + "/grp3ps/grp2ps/P5coords", + "/grp3ps/grp2ps/P6coords", + "/grp3ps/grp2ps/P7coords", + "/c3center", + "/l3point1", + "/grp2ps/c3center", + "/grp2ps/l3point1", + "/grp2ps/l6point2", + "/grp3ps/c3center", + "/grp3ps/l3point1", + "/grp3ps/grp2ps/l7point2", + "/grp3ps/grp2ps/c3center", + "/grp3ps/grp2ps/l3point1", + ]; + + for (let name of coordsNames) { + expect(stateVariables[name].stateValues.value.tree).eqls([ + "vector", + ...P, + ]); + } + + const displacementNames = [ + "/v2displacement", + "/v3displacement", + "/grp2ps/v2displacement", + "/grp2ps/v3displacement", + "/grp3ps/v2displacement", + "/grp3ps/v3displacement", + "/grp3ps/grp2ps/v2displacement", + "/grp3ps/grp2ps/v3displacement", + ]; + for (let name of displacementNames) { + expect(stateVariables[name].stateValues.value.tree).eqls([ + "vector", + ...v, + ]); + } + + const headNames = [ + "/l3point2", + "/grp2ps/l3point2", + "/grp3ps/l3point2", + "/grp3ps/grp2ps/l3point2", + "/grp3ps/grp2ps/v7head", + ]; + for (let name of headNames) { + expect(stateVariables[name].stateValues.value.tree).eqls([ + "vector", + ...vH, + ]); + } + + const centerNames = [ + "/c5center", + "/grp2ps/c5center", + "/grp2ps/l6point1", + "/grp3ps/c5center", + "/grp3ps/grp2ps/c5center", + "/grp3ps/grp2ps/l6point1", + "/grp3ps/grp2ps/l7point1", + "/grp3ps/grp2ps/v7tail", + ]; + for (let name of centerNames) { + expect(stateVariables[name].stateValues.value.tree).eqls([ + "vector", + ...c0, + ]); + } + + expect( + stateVariables["/g/P"].stateValues.xs.map((x) => x.tree), + ).eqls(P); + expect( + stateVariables["/g2/P"].stateValues.xs.map((x) => x.tree), + ).eqls(P); + expect( + stateVariables["/v"].stateValues.displacement.map( + (x) => x.tree, + ), + ).eqls(v); + expect( + stateVariables["/g3/P"].stateValues.xs.map((x) => x.tree), + ).eqls(P); + expect( + stateVariables["/g3/v"].stateValues.displacement.map( + (x) => x.tree, + ), + ).eqls(v); + expect( + stateVariables["/g3/c"].stateValues.center.map((x) => x.tree), + ).eqls(P); + expect( + stateVariables["/g3/l"].stateValues.endpoints[0].map( + (x) => x.tree, + ), + ).eqls(P); + expect( + stateVariables["/g3/l"].stateValues.endpoints[1].map( + (x) => x.tree, + ), + ).eqls(vH); + expect( + stateVariables["/g4/P"].stateValues.xs.map((x) => x.tree), + ).eqls(P); + expect( + stateVariables["/g5/P"].stateValues.xs.map((x) => x.tree), + ).eqls(P); + expect( + stateVariables["/g5/c"].stateValues.center.map((x) => x.tree), + ).eqls(c0); + + expect( + stateVariables["/grp2/g/P"].stateValues.xs.map((x) => x.tree), + ).eqls(P); + expect( + stateVariables["/grp2/g2/P"].stateValues.xs.map((x) => x.tree), + ).eqls(P); + expect( + stateVariables["/grp2/v"].stateValues.displacement.map( + (x) => x.tree, + ), + ).eqls(v); + expect( + stateVariables["/grp2/g3/P"].stateValues.xs.map((x) => x.tree), + ).eqls(P); + expect( + stateVariables["/grp2/g3/v"].stateValues.displacement.map( + (x) => x.tree, + ), + ).eqls(v); + expect( + stateVariables["/grp2/g3/c"].stateValues.center.map( + (x) => x.tree, + ), + ).eqls(P); + expect( + stateVariables["/grp2/g3/l"].stateValues.endpoints[0].map( + (x) => x.tree, + ), + ).eqls(P); + expect( + stateVariables["/grp2/g3/l"].stateValues.endpoints[1].map( + (x) => x.tree, + ), + ).eqls(vH); + expect( + stateVariables["/grp2/g4/P"].stateValues.xs.map((x) => x.tree), + ).eqls(P); + expect( + stateVariables["/grp2/g5/P"].stateValues.xs.map((x) => x.tree), + ).eqls(P); + expect( + stateVariables["/grp2/g5/c"].stateValues.center.map( + (x) => x.tree, + ), + ).eqls(c0); + expect( + stateVariables["/grp2/g6/P"].stateValues.xs.map((x) => x.tree), + ).eqls(P); + expect( + stateVariables["/grp2/g6/c"].stateValues.center.map( + (x) => x.tree, + ), + ).eqls(c0); + expect( + stateVariables["/grp2/l"].stateValues.endpoints[0].map( + (x) => x.tree, + ), + ).eqls(c0); + expect( + stateVariables["/grp2/l"].stateValues.endpoints[1].map( + (x) => x.tree, + ), + ).eqls(P); + + expect( + stateVariables["/grp3/g/P"].stateValues.xs.map((x) => x.tree), + ).eqls(P); + expect( + stateVariables["/grp3/g2/P"].stateValues.xs.map((x) => x.tree), + ).eqls(P); + expect( + stateVariables["/grp3/v"].stateValues.displacement.map( + (x) => x.tree, + ), + ).eqls(v); + expect( + stateVariables["/grp3/g3/P"].stateValues.xs.map((x) => x.tree), + ).eqls(P); + expect( + stateVariables["/grp3/g3/v"].stateValues.displacement.map( + (x) => x.tree, + ), + ).eqls(v); + expect( + stateVariables["/grp3/g3/c"].stateValues.center.map( + (x) => x.tree, + ), + ).eqls(P); + expect( + stateVariables["/grp3/g3/l"].stateValues.endpoints[0].map( + (x) => x.tree, + ), + ).eqls(P); + expect( + stateVariables["/grp3/g3/l"].stateValues.endpoints[1].map( + (x) => x.tree, + ), + ).eqls(vH); + expect( + stateVariables["/grp3/g4/P"].stateValues.xs.map((x) => x.tree), + ).eqls(P); + expect( + stateVariables["/grp3/g5/P"].stateValues.xs.map((x) => x.tree), + ).eqls(P); + expect( + stateVariables["/grp3/g5/c"].stateValues.center.map( + (x) => x.tree, + ), + ).eqls(c0); + + expect( + stateVariables["/grp3/grp2/g/P"].stateValues.xs.map( + (x) => x.tree, + ), + ).eqls(P); + expect( + stateVariables["/grp3/grp2/g2/P"].stateValues.xs.map( + (x) => x.tree, + ), + ).eqls(P); + expect( + stateVariables["/grp3/grp2/v"].stateValues.displacement.map( + (x) => x.tree, + ), + ).eqls(v); + expect( + stateVariables["/grp3/grp2/g3/P"].stateValues.xs.map( + (x) => x.tree, + ), + ).eqls(P); + expect( + stateVariables["/grp3/grp2/g3/v"].stateValues.displacement.map( + (x) => x.tree, + ), + ).eqls(v); + expect( + stateVariables["/grp3/grp2/g3/c"].stateValues.center.map( + (x) => x.tree, + ), + ).eqls(P); + expect( + stateVariables["/grp3/grp2/g3/l"].stateValues.endpoints[0].map( + (x) => x.tree, + ), + ).eqls(P); + expect( + stateVariables["/grp3/grp2/g3/l"].stateValues.endpoints[1].map( + (x) => x.tree, + ), + ).eqls(vH); + expect( + stateVariables["/grp3/grp2/g4/P"].stateValues.xs.map( + (x) => x.tree, + ), + ).eqls(P); + expect( + stateVariables["/grp3/grp2/g5/P"].stateValues.xs.map( + (x) => x.tree, + ), + ).eqls(P); + expect( + stateVariables["/grp3/grp2/g5/c"].stateValues.center.map( + (x) => x.tree, + ), + ).eqls(c0); + expect( + stateVariables["/grp3/grp2/g6/P"].stateValues.xs.map( + (x) => x.tree, + ), + ).eqls(P); + expect( + stateVariables["/grp3/grp2/g6/c"].stateValues.center.map( + (x) => x.tree, + ), + ).eqls(c0); + expect( + stateVariables["/grp3/grp2/l"].stateValues.endpoints[0].map( + (x) => x.tree, + ), + ).eqls(c0); + expect( + stateVariables["/grp3/grp2/l"].stateValues.endpoints[1].map( + (x) => x.tree, + ), + ).eqls(P); + expect( + stateVariables["/grp3/g7/P"].stateValues.xs.map((x) => x.tree), + ).eqls(P); + expect( + stateVariables["/grp3/g7/c"].stateValues.center.map( + (x) => x.tree, + ), + ).eqls(c0); + expect( + stateVariables["/grp3/g7/l"].stateValues.endpoints[0].map( + (x) => x.tree, + ), + ).eqls(c0); + expect( + stateVariables["/grp3/g7/l"].stateValues.endpoints[1].map( + (x) => x.tree, + ), + ).eqls(P); + expect( + stateVariables["/grp3/g7/v"].stateValues.head.map( + (x) => x.tree, + ), + ).eqls(vH); + expect( + stateVariables["/grp3/g7/v"].stateValues.tail.map( + (x) => x.tree, + ), + ).eqls(c0); + } + + let P = [1, 2]; + let v = [4, 5]; + let vH = [4, 5]; + let c0 = [0, 0]; + + await check_items({ P, v, vH, c0 }); + + // move objects + + P = [3, 5]; + await core.requestAction({ + event: null, + actionName: "movePoint", + componentName: "/g/P", + args: { x: P[0], y: P[1] }, + }); + v = [8, 7]; + vH = [5, 1]; + await core.requestAction({ + event: null, + actionName: "moveVector", + componentName: "/v", + args: { + headcoords: vH, + tailcoords: [vH[0] - v[0], vH[1] - v[1]], + }, + }); + c0 = [6, 0]; + await core.requestAction({ + event: null, + actionName: "moveCircle", + componentName: "/g5/c", + args: { center: c0 }, + }); + + await check_items({ P, v, vH, c0 }); + }); + + it("add children with copySource, recreated replacements include added children", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + (3,4) + + + + + (5,6) + + + + + + (7,8) + + `, + }); + + async function check_items(P: number[], Q: number[]) { + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/g1"].activeChildren.length).eq(1); + expect(stateVariables["/g1"].activeChildren[0].componentName).eq( + "/g1/P", + ); + expect( + stateVariables["/g1/P"].stateValues.xs.map((x) => x.tree), + ).eqls(P); + expect(stateVariables["/g2"].activeChildren.length).eq(2); + expect(stateVariables["/g2"].activeChildren[0].componentName).eq( + "/g2/P", + ); + expect(stateVariables["/g2"].activeChildren[1].componentName).eq( + "/g2/Q", + ); + expect( + stateVariables["/g2/P"].stateValues.xs.map((x) => x.tree), + ).eqls(P); + expect( + stateVariables["/g2/Q"].stateValues.xs.map((x) => x.tree), + ).eqls(Q); + } + + let P = [5, 6], + Q = [7, 8]; + + await check_items(P, Q); + + // move points + + P = [10, 9]; + Q = [8, 4]; + await core.requestAction({ + event: null, + actionName: "movePoint", + componentName: "/g1/P", + args: { x: P[0], y: P[1] }, + }); + await core.requestAction({ + event: null, + actionName: "movePoint", + componentName: "/g2/Q", + args: { x: Q[0], y: Q[1] }, + }); + + await check_items(P, Q); + + // switch to second option from conditional content + P = [3, 4]; + Q = [7, 8]; + await updateMathInputValue({ latex: "2", componentName: "/n", core }); + await check_items(P, Q); + + // move new points + P = [6, 1]; + Q = [9, 3]; + await core.requestAction({ + event: null, + actionName: "movePoint", + componentName: "/g1/P", + args: { x: P[0], y: P[1] }, + }); + await core.requestAction({ + event: null, + actionName: "movePoint", + componentName: "/g2/Q", + args: { x: Q[0], y: Q[1] }, + }); + await check_items(P, Q); + + // switch back to first option from conditional content + P = [5, 6]; + Q = [7, 8]; + await updateMathInputValue({ latex: "0", componentName: "/n", core }); + }); + + async function test_assign_names_group_map(core) { + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.value).eq("hi 1"); + expect(stateVariables["/b"].stateValues.value).eq("hi 2"); + expect(stateVariables["/c"].stateValues.value).eq("hi 1"); + expect(stateVariables["/d"].stateValues.value).eq("hi 2"); + expect(stateVariables["/e"].stateValues.value).eq("apple"); + expect(stateVariables["/f"].stateValues.value).eq("banana"); + expect(stateVariables["/g"].stateValues.value).eq("apple"); + expect(stateVariables["/h"].stateValues.value).eq("banana"); + } + + it("assign names with copySource of group and map", async () => { + let core = await createTestCore({ + doenetML: ` + + + 12 + + + + + + + apple + banana + + + + + `, + }); + + await test_assign_names_group_map(core); + }); + + it("assign names with macro copy of group and map", async () => { + let core = await createTestCore({ + doenetML: ` + + + 12 + + + $map1{name="map2" assignNames="(c) (d)"} + + + + apple + banana + + + $grp1{name="grp2" assignNames="g h"} + + `, + }); + + await test_assign_names_group_map(core); + }); + + async function test_assign_names_group_map_new_namespace(core) { + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/map1/a/t"].stateValues.value).eq("hi 1"); + expect(stateVariables["/map1/b/t"].stateValues.value).eq("hi 2"); + expect(stateVariables["/map2/c/t"].stateValues.value).eq("hi 1"); + expect(stateVariables["/map2/d/t"].stateValues.value).eq("hi 2"); + expect(stateVariables["/grp1/a"].stateValues.value).eq("apple"); + expect(stateVariables["/grp1/b"].stateValues.value).eq("banana"); + expect(stateVariables["/grp2/c"].stateValues.value).eq("apple"); + expect(stateVariables["/grp2/d"].stateValues.value).eq("banana"); + } + + it("assign names with copySource of group and map, newNamespace", async () => { + let core = await createTestCore({ + doenetML: ` + + + 12 + + + + + + + apple + banana + + + + + `, + }); + + await test_assign_names_group_map_new_namespace(core); + }); + + it("assign names with macro copy of group and map, newNamespace", async () => { + let core = await createTestCore({ + doenetML: ` + + + 12 + + + $map1{name="map2" assignNames="c d"} + + + + apple + banana + + + $grp1{name="grp2" assignNames="c d"} + + `, + }); + + await test_assign_names_group_map_new_namespace(core); + }); + + async function test_composite_replacement_skips_assign_names(core) { + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a"].stateValues.value).eq("hi"); + expect(stateVariables["/b"].stateValues.value).eq("bye"); + expect(stateVariables["/c"].stateValues.value).eq("hi"); + expect(stateVariables["/d"].stateValues.value).eq("bye"); + expect(stateVariables["/p2/c"].stateValues.value).eq("hi"); + expect(stateVariables["/p2/d"].stateValues.value).eq("bye"); + } + + it("copySource composite replacement implicitly skips assignNames", async () => { + let core = await createTestCore({ + doenetML: ` + hi + bye + + + + + + +

+ +

+ +

+ + `, + }); + + await test_composite_replacement_skips_assign_names(core); + }); + + it("macro copy composite replacement implicitly skips assignNames", async () => { + let core = await createTestCore({ + doenetML: ` + hi + bye + + + $t1 + $t2 + + +

+ $group1{assignNames="c d"} +

+ + $p1{name="p2" newNamespace} + + `, + }); + + await test_composite_replacement_skips_assign_names(core); + }); + + it("copy and macro's prescribed name is used to assign name to replacement", async () => { + let core = await createTestCore({ + doenetML: ` + hi + + $t1{name="t3"} + + + apple + banana + + + $grp1{name="grp3"} + + (3,4) + + + $p.x{assignNames="x3"} + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/t1"].stateValues.value).eq("hi"); + expect(stateVariables["/t2"].stateValues.value).eq("hi"); + expect(stateVariables["/t3"].stateValues.value).eq("hi"); + + expect(stateVariables["/grp1/text1"].stateValues.value).eq("apple"); + expect(stateVariables["/grp1/text2"].stateValues.value).eq("banana"); + expect(stateVariables["/grp2/text1"].stateValues.value).eq("apple"); + expect(stateVariables["/grp2/text2"].stateValues.value).eq("banana"); + expect(stateVariables["/grp3/text1"].stateValues.value).eq("apple"); + expect(stateVariables["/grp3/text2"].stateValues.value).eq("banana"); + + expect(stateVariables["/p"].stateValues.xs.map((x) => x.tree)).eqls([ + 3, 4, + ]); + expect(stateVariables["/x1"].stateValues.value.tree).eq(3); + expect(stateVariables["/x2"].stateValues.value.tree).eq(3); + expect(stateVariables["/x3"].stateValues.value.tree).eq(3); + }); + + it("copy's automatically generated name not used", async () => { + let core = await createTestCore({ + doenetML: ` + hi $t1{name="t2"} + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/t1"].stateValues.value).eq("hi"); + expect(stateVariables["/t2"].stateValues.value).eq("hi"); + expect(stateVariables["/_copy1"]).eq(undefined); + }); + + it("copy and macro's assignNames is used to assign name to prop replacement", async () => { + let core = await createTestCore({ + doenetML: ` + (3,4) + + $p.x{assignNames="x2"} + + + $p.coords{assignNames="c2"} + + + $p.xs{assignNames="x12 x22"} + + `, + }); + + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p"].stateValues.xs.map((x) => x.tree)).eqls([ + 3, 4, + ]); + expect(stateVariables["/x1"].stateValues.value.tree).eq(3); + expect(stateVariables["/x2"].stateValues.value.tree).eq(3); + expect(stateVariables["/c1"].stateValues.value.tree).eqls([ + "vector", + 3, + 4, + ]); + expect(stateVariables["/c2"].stateValues.value.tree).eqls([ + "vector", + 3, + 4, + ]); + expect(stateVariables["/x11"].stateValues.value.tree).eq(3); + expect(stateVariables["/x21"].stateValues.value.tree).eq(4); + expect(stateVariables["/x12"].stateValues.value.tree).eq(3); + expect(stateVariables["/x22"].stateValues.value.tree).eq(4); + }); + + it("add children to copySource with prop and propIndex", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + +

P:

+

label of P:

+ + + `, + }); + + async function check_items(ind: number) { + const stateVariables = await returnAllStateVariables(core); + + if (ind === 1) { + expect(stateVariables["/Pa"].stateValues.coords.tree).eqls([ + "vector", + 1, + 2, + ]); + expect(stateVariables["/l"].stateValues.value).eq("\\(V_ 1\\)"); + expect( + stateVariables["/P"].stateValues.xs.map((x) => x.tree), + ).eqls([1, 2]); + expect(stateVariables["/P"].stateValues.label).eq("\\(V_ 1\\)"); + } else if (ind === 2) { + expect(stateVariables["/Pa"].stateValues.coords.tree).eqls([ + "vector", + 5, + 2, + ]); + expect(stateVariables["/l"].stateValues.value).eq("\\(V_ 2\\)"); + expect( + stateVariables["/P"].stateValues.xs.map((x) => x.tree), + ).eqls([5, 2]); + expect(stateVariables["/P"].stateValues.label).eq("\\(V_ 2\\)"); + } else if (ind === 3) { + expect(stateVariables["/Pa"].stateValues.coords.tree).eqls([ + "vector", + 5, + 8, + ]); + expect(stateVariables["/l"].stateValues.value).eq("\\(V_ 3\\)"); + expect( + stateVariables["/P"].stateValues.xs.map((x) => x.tree), + ).eqls([5, 8]); + expect(stateVariables["/P"].stateValues.label).eq("\\(V_ 3\\)"); + } else { + expect(stateVariables["/Pa"].stateValues.coords.tree).eqls([ + "vector", + 0, + 0, + ]); + expect(stateVariables["/l"].stateValues.value).eq(""); + expect( + stateVariables["/P"].stateValues.xs.map((x) => x.tree), + ).eqls([0, 0]); + expect(stateVariables["/P"].stateValues.label).eq(""); + } + } + + await check_items(1); + + // change to vertex 2 + await updateMathInputValue({ latex: "2", componentName: "/ind", core }); + await check_items(2); + + // invalid vertex + await updateMathInputValue({ latex: "", componentName: "/ind", core }); + await check_items(0); + + // change to vertex 3 + await updateMathInputValue({ latex: "3", componentName: "/ind", core }); + await check_items(3); + }); + + it("dot and array notation", async () => { + let core = await createTestCore({ + doenetML: ` + + (2,3) + + +

P: $P

+

P: $P[1]

+

nothing: $P[2]

+

P.: $P.

+

P.1: $P.1

+

x of P: $P.x

+

y of P: $P.y

+

nothing: $P._x

+

x of P: $P.xs[1]

+

y of P: $P.xs[2]

+

nothing: $P.xs[3]

+ + +

P: $(P)

+

(P).x: $(P).x

+

no match: $(P.)

+

nothing: $(P.1)

+

x of P: $(P.x)

+

y of P: $(P.y)

+

x of P: $(P.xs[1])

+

y of P: $(P.xs[2])

+ + +

P:

+

P:

+

nothing:

+

nothing:

+

nothing:

+

x of P:

+

y of P:

+

nothing:

+

x of P:

+

y of P:

+

nothing:

+ `, + }); + + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p1"].stateValues.text).eq("P: ( 2, 3 )"); + expect(stateVariables["/p2"].stateValues.text).eq("P: ( 2, 3 )"); + expect(stateVariables["/p3"].stateValues.text).eq("nothing: "); + expect(stateVariables["/p4"].stateValues.text).eq("P.: ( 2, 3 )."); + expect(stateVariables["/p5"].stateValues.text).eq("P.1: ( 2, 3 ).1"); + expect(stateVariables["/p6"].stateValues.text).eq("x of P: 2"); + expect(stateVariables["/p7"].stateValues.text).eq("y of P: 3"); + expect(stateVariables["/p8"].stateValues.text).eq("nothing: "); + expect(stateVariables["/p9"].stateValues.text).eq("x of P: 2"); + expect(stateVariables["/p10"].stateValues.text).eq("y of P: 3"); + expect(stateVariables["/p11"].stateValues.text).eq("nothing: "); + + expect(stateVariables["/p12"].stateValues.text).eq("P: ( 2, 3 )"); + expect(stateVariables["/p13"].stateValues.text).eq("(P).x: ( 2, 3 ).x"); + expect(stateVariables["/p14"].stateValues.text).eq("no match: $(P.)"); + expect(stateVariables["/p15"].stateValues.text).eq("nothing: "); + expect(stateVariables["/p16"].stateValues.text).eq("x of P: 2"); + expect(stateVariables["/p17"].stateValues.text).eq("y of P: 3"); + expect(stateVariables["/p18"].stateValues.text).eq("x of P: 2"); + expect(stateVariables["/p19"].stateValues.text).eq("y of P: 3"); + + expect(stateVariables["/p20"].stateValues.text).eq("P: ( 2, 3 )"); + expect(stateVariables["/p21"].stateValues.text).eq("P: ( 2, 3 )"); + expect(stateVariables["/p22"].stateValues.text).eq("nothing: "); + expect(stateVariables["/p23"].stateValues.text).eq("nothing: "); + expect(stateVariables["/p24"].stateValues.text).eq("nothing: "); + expect(stateVariables["/p25"].stateValues.text).eq("x of P: 2"); + expect(stateVariables["/p26"].stateValues.text).eq("y of P: 3"); + expect(stateVariables["/p27"].stateValues.text).eq("nothing: "); + expect(stateVariables["/p28"].stateValues.text).eq("x of P: 2"); + expect(stateVariables["/p29"].stateValues.text).eq("y of P: 3"); + expect(stateVariables["/p30"].stateValues.text).eq("nothing: "); + }); + + it("dot and array notation, chaining, macros", async () => { + let core = await createTestCore({ + doenetML: ` + + + + +

$l.points.coords

+

$l.points.x

+

$l.points.y

+

$l.points.bad

+

$l.points.xs[1]

+

$l.points.xs[2]

+

$l.points.xs[3]

+ +

$l.points[1].coords

+

$l.points[1].x

+

$l.points[1].y

+

$l.points[1].bad

+

$l.points[1].xs[1]

+

$l.points[1].xs[2]

+

$l.points[1].xs[3]

+ +

$l.points[2].coords

+

$l.points[2].x

+

$l.points[2].y

+

$l.points[2].bad

+

$l.points[2].xs[1]

+

$l.points[2].xs[2]

+

$l.points[2].xs[3]

+ +

$l.points[3].coords

+

$l.points[3].x

+

$l.points[3].y

+

$l.points[3].bad

+

$l.points[3].xs[1]

+

$l.points[3].xs[2]

+

$l.points[3].xs[3]

+ +

$l.points.coords.latex

+

$l.points.x.latex

+

$l.points.y.latex

+

$l.points.bad.latex

+

$l.points.xs[1].latex

+

$l.points.xs[2].latex

+

$l.points.xs[3].latex

+ +

$l.points[1].coords.latex

+

$l.points[1].x.latex

+

$l.points[1].y.latex

+

$l.points[1].bad.latex

+

$l.points[1].xs[1].latex

+

$l.points[1].xs[2].latex

+

$l.points[1].xs[3].latex

+ +

$l.points[1][1]

+

$l.points[1][2]

+

$l.points[2][1]

+

$l.points[2][2]

+

$l.points[0][1]

+

$l.points[1][0]

+

$l.points[1][3]

+

$l.points[3][1]

+ + `, + }); + + async function check_items({ + P11, + P12, + P21, + P22, + P11latex, + }: { + P11: string; + P12: string; + P21: string; + P22: string; + P11latex?: string; + }) { + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p1"].stateValues.text).eq( + `( ${P11}, ${P12} ), ( ${P21}, ${P22} )`, + ); + expect(stateVariables["/p2"].stateValues.text).eq(`${P11}, ${P21}`); + expect(stateVariables["/p3"].stateValues.text).eq(`${P12}, ${P22}`); + expect(stateVariables["/p4"].stateValues.text).eq(``); + expect(stateVariables["/p5"].stateValues.text).eq(`${P11}, ${P21}`); + expect(stateVariables["/p6"].stateValues.text).eq(`${P12}, ${P22}`); + expect(stateVariables["/p7"].stateValues.text).eq(``); + + expect(stateVariables["/p8"].stateValues.text).eq( + `( ${P11}, ${P12} )`, + ); + expect(stateVariables["/p9"].stateValues.text).eq(`${P11}`); + expect(stateVariables["/p10"].stateValues.text).eq(`${P12}`); + expect(stateVariables["/p11"].stateValues.text).eq(``); + expect(stateVariables["/p12"].stateValues.text).eq(`${P11}`); + expect(stateVariables["/p13"].stateValues.text).eq(`${P12}`); + expect(stateVariables["/p14"].stateValues.text).eq(``); + + expect(stateVariables["/p15"].stateValues.text).eq( + `( ${P21}, ${P22} )`, + ); + expect(stateVariables["/p16"].stateValues.text).eq(`${P21}`); + expect(stateVariables["/p17"].stateValues.text).eq(`${P22}`); + expect(stateVariables["/p18"].stateValues.text).eq(``); + expect(stateVariables["/p19"].stateValues.text).eq(`${P21}`); + expect(stateVariables["/p20"].stateValues.text).eq(`${P22}`); + expect(stateVariables["/p21"].stateValues.text).eq(``); + + expect(stateVariables["/p22"].stateValues.text).eq(``); + expect(stateVariables["/p23"].stateValues.text).eq(``); + expect(stateVariables["/p24"].stateValues.text).eq(``); + expect(stateVariables["/p25"].stateValues.text).eq(``); + expect(stateVariables["/p26"].stateValues.text).eq(``); + expect(stateVariables["/p27"].stateValues.text).eq(``); + expect(stateVariables["/p28"].stateValues.text).eq(``); + + expect(cleanLatex(stateVariables["/p29"].stateValues.text)).eq( + `(${P11latex || P11},${P12}),(${P21},${P22})`, + ); + expect(cleanLatex(stateVariables["/p30"].stateValues.text)).eq( + `${P11latex || P11},${P21}`, + ); + expect(cleanLatex(stateVariables["/p31"].stateValues.text)).eq( + `${P12},${P22}`, + ); + expect(cleanLatex(stateVariables["/p32"].stateValues.text)).eq(``); + expect(cleanLatex(stateVariables["/p33"].stateValues.text)).eq( + `${P11latex || P11},${P21}`, + ); + expect(cleanLatex(stateVariables["/p34"].stateValues.text)).eq( + `${P12},${P22}`, + ); + expect(cleanLatex(stateVariables["/p35"].stateValues.text)).eq(``); + + expect(cleanLatex(stateVariables["/p36"].stateValues.text)).eq( + `(${P11latex || P11},${P12})`, + ); + expect(cleanLatex(stateVariables["/p37"].stateValues.text)).eq( + `${P11latex || P11}`, + ); + expect(cleanLatex(stateVariables["/p38"].stateValues.text)).eq( + `${P12}`, + ); + expect(cleanLatex(stateVariables["/p39"].stateValues.text)).eq(``); + expect(cleanLatex(stateVariables["/p40"].stateValues.text)).eq( + `${P11latex || P11}`, + ); + expect(cleanLatex(stateVariables["/p41"].stateValues.text)).eq( + `${P12}`, + ); + expect(cleanLatex(stateVariables["/p42"].stateValues.text)).eq(``); + + expect(stateVariables["/p43"].stateValues.text).eq(`${P11}`); + expect(stateVariables["/p44"].stateValues.text).eq(`${P12}`); + expect(stateVariables["/p45"].stateValues.text).eq(`${P21}`); + expect(stateVariables["/p46"].stateValues.text).eq(`${P22}`); + expect(stateVariables["/p47"].stateValues.text).eq(``); + expect(stateVariables["/p48"].stateValues.text).eq(``); + expect(stateVariables["/p49"].stateValues.text).eq(``); + expect(stateVariables["/p50"].stateValues.text).eq(``); + } + + await check_items({ + P11: "2/3", + P12: "3", + P21: "5", + P22: "6", + P11latex: "\\frac{2}{3}", + }); + + // move points + + await core.requestAction({ + event: null, + actionName: "moveLine", + componentName: "/l", + args: { + point1coords: [7, 8], + point2coords: [9, 0], + }, + }); + + await check_items({ + P11: "7", + P12: "8", + P21: "9", + P22: "0", + }); + }); + + it("dot and array notation, chaining, specify attributes, macros", async () => { + let core = await createTestCore({ + doenetML: ` + + + + +

$l.points.coords

+

$l.points.x

+

$l.points.y

+

$l.points.bad

+

$l.points.xs[1]

+

$l.points.xs[2]

+

$l.points.xs[3]

+ +

$(l.points.coords{displayDecimals="4"})

+

$(l.points.x{displayDecimals="4"})

+

$(l.points.y{displayDecimals="4"})

+

$(l.points.bad{displayDecimals="4"})

+

$(l.points.xs[1]{displayDecimals="4"})

+

$(l.points.xs[2]{displayDecimals="4"})

+

$(l.points.xs[3]{displayDecimals="4"})

+ +

$(l.points[1].coords{displayDecimals="4"})

+

$(l.points[1].x{displayDecimals="4"})

+

$(l.points[1].y{displayDecimals="4"})

+

$(l.points[1].bad{displayDecimals="4"})

+

$(l.points[1].xs[1]{displayDecimals="4"})

+

$(l.points[1].xs[2]{displayDecimals="4"})

+

$(l.points[1].xs[3]{displayDecimals="4"})

+ +

$l.points.coords{displayDecimals="4"}

+

$l.points{displayDecimals="4"}.x

+

$l{displayDecimals="4"}.points.y

+

$l.points.bad{displayDecimals="4"}

+

$l.points.xs[1]{displayDecimals="4"}

+

$l.points{displayDecimals="4"}.xs[2]

+

$l{displayDecimals="4"}.points.xs[3]

+ +

$l.points[1].coords{displayDecimals="4"}

+

$l.points[1]{displayDecimals="4"}.x

+

$l{displayDecimals="4"}.points[1].y

+

$l.points[1].bad{displayDecimals="4"}

+

$l.points[1].xs[1]{displayDecimals="4"}

+

$l.points[1]{displayDecimals="4"}.xs[2]

+

$l{displayDecimals="4"}.points[1].xs[3]

+ +

$l{displayDecimals="4"}.latex

+

$(l{displayDigits="3"}.points{displayDecimals="4"})

+

$(l{displayDigits="3"}.points[1]{displayDecimals="4"})

+ + `, + }); + + function round({ + val, + digits, + decimals, + }: { + val: number; + digits?: number; + decimals?: number; + }) { + return me.round_numbers_to_precision_plus_decimals( + val, + digits === undefined ? 0 : digits, + decimals === undefined ? -Infinity : decimals, + ).tree; + } + + let P11 = 3.92639372, + P12 = 9.8293629453, + P21 = 0.9060742037, + P22 = 32.93520806203104; + + let P11Dig2 = round({ val: P11, digits: 2 }); + let P12Dig2 = round({ val: P12, digits: 2 }); + let P21Dig2 = round({ val: P21, digits: 2 }); + let P22Dig2 = round({ val: P22, digits: 2 }); + + let P11Dec4 = round({ val: P11, decimals: 4 }); + let P12Dec4 = round({ val: P12, decimals: 4 }); + let P21Dec4 = round({ val: P21, decimals: 4 }); + let P22Dec4 = round({ val: P22, decimals: 4 }); + + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p1"].stateValues.text).eq( + `( ${P11Dig2}, ${P12Dig2} ), ( ${P21Dig2}, ${P22Dig2} )`, + ); + expect(stateVariables["/p2"].stateValues.text).eq( + `${P11Dig2}, ${P21Dig2}`, + ); + expect(stateVariables["/p3"].stateValues.text).eq( + `${P12Dig2}, ${P22Dig2}`, + ); + expect(stateVariables["/p4"].stateValues.text).eq(``); + expect(stateVariables["/p5"].stateValues.text).eq( + `${P11Dig2}, ${P21Dig2}`, + ); + expect(stateVariables["/p6"].stateValues.text).eq( + `${P12Dig2}, ${P22Dig2}`, + ); + expect(stateVariables["/p7"].stateValues.text).eq(``); + + expect(stateVariables["/p8"].stateValues.text).eq( + `( ${P11Dec4}, ${P12Dec4} ), ( ${P21Dec4}, ${P22Dec4} )`, + ); + expect(stateVariables["/p9"].stateValues.text).eq( + `${P11Dec4}, ${P21Dec4}`, + ); + expect(stateVariables["/p10"].stateValues.text).eq( + `${P12Dec4}, ${P22Dec4}`, + ); + expect(stateVariables["/p11"].stateValues.text).eq(``); + expect(stateVariables["/p12"].stateValues.text).eq( + `${P11Dec4}, ${P21Dec4}`, + ); + expect(stateVariables["/p13"].stateValues.text).eq( + `${P12Dec4}, ${P22Dec4}`, + ); + expect(stateVariables["/p14"].stateValues.text).eq(``); + + expect(stateVariables["/p15"].stateValues.text).eq( + `( ${P11Dec4}, ${P12Dec4} )`, + ); + expect(stateVariables["/p16"].stateValues.text).eq(`${P11Dec4}`); + expect(stateVariables["/p17"].stateValues.text).eq(`${P12Dec4}`); + expect(stateVariables["/p18"].stateValues.text).eq(``); + expect(stateVariables["/p19"].stateValues.text).eq(`${P11Dec4}`); + expect(stateVariables["/p20"].stateValues.text).eq(`${P12Dec4}`); + expect(stateVariables["/p21"].stateValues.text).eq(``); + + expect(stateVariables["/p22"].stateValues.text).eq( + `( ${P11Dec4}, ${P12Dec4} ), ( ${P21Dec4}, ${P22Dec4} )`, + ); + expect(stateVariables["/p23"].stateValues.text).eq( + `${P11Dec4}, ${P21Dec4}`, + ); + expect(stateVariables["/p24"].stateValues.text).eq( + `${P12Dec4}, ${P22Dec4}`, + ); + expect(stateVariables["/p25"].stateValues.text).eq(``); + expect(stateVariables["/p26"].stateValues.text).eq( + `${P11Dec4}, ${P21Dec4}`, + ); + expect(stateVariables["/p27"].stateValues.text).eq( + `${P12Dec4}, ${P22Dec4}`, + ); + expect(stateVariables["/p28"].stateValues.text).eq(``); + + expect(stateVariables["/p29"].stateValues.text).eq( + `( ${P11Dec4}, ${P12Dec4} )`, + ); + expect(stateVariables["/p30"].stateValues.text).eq(`${P11Dec4}`); + expect(stateVariables["/p31"].stateValues.text).eq(`${P12Dec4}`); + expect(stateVariables["/p32"].stateValues.text).eq(``); + expect(stateVariables["/p33"].stateValues.text).eq(`${P11Dec4}`); + expect(stateVariables["/p34"].stateValues.text).eq(`${P12Dec4}`); + expect(stateVariables["/p35"].stateValues.text).eq(``); + + expect(stateVariables["/p36"].stateValues.text).eq( + "0 = -23.1058 x - 3.0203 y + 120.4105", + ); + + expect(stateVariables["/p37"].stateValues.text).eq( + `( ${P11Dec4}, ${P12Dec4} ), ( ${P21Dec4}, ${P22Dec4} )`, + ); + expect(stateVariables["/p38"].stateValues.text).eq( + `( ${P11Dec4}, ${P12Dec4} )`, + ); + }); + + it("dot and array notation, chaining, nested", async () => { + let core = await createTestCore({ + doenetML: ` + + + $l.points + + +

+ $l[1].points[$l.points[1].x]{displayDigits="$l.points[2].x"}.y +

+

+ +

+ + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p1"].stateValues.text).eq("2.93521"); + expect(stateVariables["/p2"].stateValues.text).eq("2.93521"); + + await core.requestAction({ + event: null, + actionName: "moveLine", + componentName: "/l", + args: { + point1coords: [1.38527302734, 8.48273402357], + point2coords: [5.9060742037, 2.93520806203104], + }, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p1"].stateValues.text).eq("8.48273"); + expect(stateVariables["/p2"].stateValues.text).eq("8.48273"); + + await core.requestAction({ + event: null, + actionName: "moveLine", + componentName: "/l", + args: { + point1coords: [1.38527302734, 8.48273402357], + point2coords: [4.482081034234, 7.34828203481], + }, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p1"].stateValues.text).eq("8.483"); + expect(stateVariables["/p2"].stateValues.text).eq("8.483"); + }); + + it("dot and array notation, chaining, copy source, change type", async () => { + let core = await createTestCore({ + doenetML: ` + + + + +

+

+

+

+

+

+

+ +

+

+

+

+

+

+

+ +

+

+

+

+

+

+

+ +

+

+

+

+

+

+

+ +

+

+

+

+

+

+

+ +

+

+

+

+

+

+

+ +

+

+

+

+

+

+

+

+ `, + }); + + async function check_items({ + P11, + P12, + P21, + P22, + P11latex, + P12latex, + P21latex, + P22latex, + P11string, + P12string, + P21string, + P22string, + }: { + P11: number; + P12: number; + P21: number; + P22: number; + P11latex?: string; + P12latex?: string; + P21latex?: string; + P22latex?: string; + P11string?: string; + P12string?: string; + P21string?: string; + P22string?: string; + }) { + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p1"].stateValues.text).eq( + `( ${P11string || P11}, ${P12string || P12} ), ( ${P21string || P21}, ${P22string || P22} )`, + ); + + expect(stateVariables["/p2"].stateValues.text).eq(`${P11}, ${P21}`); + expect(stateVariables["/p3"].stateValues.text).eq(`${P12}, ${P22}`); + expect(stateVariables["/p4"].stateValues.text).eq(`NaN, NaN`); + expect(stateVariables["/p5"].stateValues.text).eq(`${P11}, ${P21}`); + expect(stateVariables["/p6"].stateValues.text).eq(`${P12}, ${P22}`); + expect(stateVariables["/p7"].stateValues.text).eq(`NaN, NaN`); + + expect(stateVariables["/p8"].stateValues.text).eq( + `( ${P11string || P11}, ${P12string || P12} )`, + ); + expect(stateVariables["/p9"].stateValues.text).eq(`${P11}`); + expect(stateVariables["/p10"].stateValues.text).eq(`${P12}`); + expect(stateVariables["/p11"].stateValues.text).eq(`NaN`); + expect(stateVariables["/p12"].stateValues.text).eq(`${P11}`); + expect(stateVariables["/p13"].stateValues.text).eq(`${P12}`); + expect(stateVariables["/p14"].stateValues.text).eq(`NaN`); + + expect(stateVariables["/p15"].stateValues.text).eq( + `( ${P21string || P21}, ${P22string || P22} )`, + ); + expect(stateVariables["/p16"].stateValues.text).eq(`${P21}`); + expect(stateVariables["/p17"].stateValues.text).eq(`${P22}`); + expect(stateVariables["/p18"].stateValues.text).eq(`NaN`); + expect(stateVariables["/p19"].stateValues.text).eq(`${P21}`); + expect(stateVariables["/p20"].stateValues.text).eq(`${P22}`); + expect(stateVariables["/p21"].stateValues.text).eq(`NaN`); + + expect(stateVariables["/p22"].stateValues.text).eq(`\uff3f`); + expect(stateVariables["/p23"].stateValues.text).eq(`NaN`); + expect(stateVariables["/p24"].stateValues.text).eq(`NaN`); + expect(stateVariables["/p25"].stateValues.text).eq(`NaN`); + expect(stateVariables["/p26"].stateValues.text).eq(`NaN`); + expect(stateVariables["/p27"].stateValues.text).eq(`NaN`); + expect(stateVariables["/p28"].stateValues.text).eq(`NaN`); + + expect(cleanLatex(stateVariables["/p29"].stateValues.text)).eq( + `(${P11latex || P11},${P12latex || P12}),(${P21latex || P21},${P22latex || P22})`, + ); + expect(cleanLatex(stateVariables["/p30"].stateValues.text)).eq( + `${P11latex || P11},${P21latex || P21}`, + ); + expect(cleanLatex(stateVariables["/p31"].stateValues.text)).eq( + `${P12latex || P12},${P22latex || P22}`, + ); + expect(cleanLatex(stateVariables["/p32"].stateValues.text)).eq(``); + expect(cleanLatex(stateVariables["/p33"].stateValues.text)).eq( + `${P11latex || P11},${P21latex || P21}`, + ); + expect(cleanLatex(stateVariables["/p34"].stateValues.text)).eq( + `${P12latex || P12},${P22latex || P22}`, + ); + expect(cleanLatex(stateVariables["/p35"].stateValues.text)).eq(``); + + expect(cleanLatex(stateVariables["/p36"].stateValues.text)).eq( + `(${P11latex || P11},${P12latex || P12})`, + ); + expect(cleanLatex(stateVariables["/p37"].stateValues.text)).eq( + `${P11latex || P11}`, + ); + expect(cleanLatex(stateVariables["/p38"].stateValues.text)).eq( + `${P12latex || P12}`, + ); + expect(cleanLatex(stateVariables["/p39"].stateValues.text)).eq(``); + expect(cleanLatex(stateVariables["/p40"].stateValues.text)).eq( + `${P11latex || P11}`, + ); + expect(cleanLatex(stateVariables["/p41"].stateValues.text)).eq( + `${P12latex || P12}`, + ); + expect(cleanLatex(stateVariables["/p42"].stateValues.text)).eq(``); + + expect(stateVariables["/p43"].stateValues.text).eq(`${P11}`); + expect(stateVariables["/p44"].stateValues.text).eq(`${P12}`); + expect(stateVariables["/p45"].stateValues.text).eq(`${P21}`); + expect(stateVariables["/p46"].stateValues.text).eq(`${P22}`); + expect(stateVariables["/p47"].stateValues.text).eq(`NaN`); + expect(stateVariables["/p48"].stateValues.text).eq(`NaN`); + expect(stateVariables["/p49"].stateValues.text).eq(`NaN`); + expect(stateVariables["/p50"].stateValues.text).eq(`NaN`); + } + + await check_items({ + P11: 0.67, + P12: 0.75, + P21: 0.63, + P22: 0.6, + P11latex: "\\frac{2}{3}", + P12latex: "\\frac{3}{4}", + P21latex: "\\frac{5}{8}", + P22latex: "\\frac{3}{5}", + P11string: "2/3", + P12string: "3/4", + P21string: "5/8", + P22string: "3/5", + }); + + // move points + await core.requestAction({ + event: null, + actionName: "moveLine", + componentName: "/l", + args: { + point1coords: [7, 8], + point2coords: [9, 0], + }, + }); + + await check_items({ + P11: 7, + P12: 8, + P21: 9, + P22: 0, + }); + }); + + it("dot and array notation, multidimensional, dynamic", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + +

Line number:

+

Point number:

+

Coordinate number:

+ + +

$col[$ln].points[$pn][$cn]

+

+

$col[$ln].points[$pn].xs[$cn]

+

+ + `, + }); + + async function check_items({ + ln, + pn, + cn, + }: { + ln: number; + pn: number; + cn: number; + }) { + const stateVariables = await returnAllStateVariables(core); + + let values = [ + [ + [1, 2], + [3, 4], + ], + [ + [5, 7], + [9, 6], + ], + ]; + + let val = values[ln - 1]?.[pn - 1]?.[cn - 1]; + + if (val !== undefined) { + expect(stateVariables["/p1"].stateValues.text).eq(`${val}`); + expect(stateVariables["/p2"].stateValues.text).eq(`${val}`); + expect(stateVariables["/p3"].stateValues.text).eq(`${val}`); + expect(stateVariables["/p4"].stateValues.text).eq(`${val}`); + } else { + expect(stateVariables["/p1"].stateValues.text).eq(""); + expect(stateVariables["/p2"].stateValues.text).eq(""); + expect(stateVariables["/p3"].stateValues.text).eq(""); + expect(stateVariables["/p4"].stateValues.text).eq(""); + } + } + + await check_items({ ln: 1, pn: 1, cn: 1 }); + + await updateMathInputValue({ latex: "", componentName: "/ln", core }); + await check_items({ ln: 0, pn: 1, cn: 1 }); + + await updateMathInputValue({ latex: "2", componentName: "/ln", core }); + await check_items({ ln: 2, pn: 1, cn: 1 }); + + await updateMathInputValue({ latex: "0", componentName: "/pn", core }); + await check_items({ ln: 2, pn: 0, cn: 1 }); + + await updateMathInputValue({ latex: "2", componentName: "/pn", core }); + await check_items({ ln: 2, pn: 2, cn: 1 }); + + await updateMathInputValue({ latex: "", componentName: "/cn", core }); + await check_items({ ln: 2, pn: 2, cn: 0 }); + + await updateMathInputValue({ latex: "2", componentName: "/cn", core }); + await check_items({ ln: 2, pn: 2, cn: 2 }); + }); + + it("dot and array notation, recurse to subnames of composite replacements", async () => { + let core = await createTestCore({ + doenetML: ` +

n:

+ + + + + + +

Template number:

+

Point number:

+

Coordinate number:

+ +

The points from template $tn are: $(myMap[$tn]/P) and .

+

Point $pn from the line in that template is: $(myMap[$tn]/l.points[$pn]).

+

Coordinate $cn from that point is $(myMap[$tn]/l.points[$pn].xs[$cn]).

+

Again, coordinate $cn from that point is .

+ + `, + }); + + let Pxs = [2, 3, 4, 5, 6]; + let Pys = [3, 4, 5, 6, 7]; + let Qxs = [5, 6, 7, 8, 9]; + let Qys = [0, 1, 2, 3, 4]; + + async function check_items(n, tn, pn, cn) { + const stateVariables = await returnAllStateVariables(core); + + if (!(n >= 1 && tn <= n)) { + // we have nothing + expect(stateVariables["/pt"].stateValues.text).contain( + "are: and .", + ); + expect(stateVariables["/pp"].stateValues.text).contain( + "from the line in that template is: .", + ); + expect(stateVariables["/pc"].stateValues.text).contain( + "from that point is .", + ); + expect(stateVariables["/pc2"].stateValues.text).contain( + "from that point is .", + ); + } else { + expect(stateVariables["/pt"].stateValues.text).contain( + `are: ( ${Pxs[tn - 1]}, ${Pys[tn - 1]} ) and ( ${Qxs[tn - 1]}, ${Qys[tn - 1]} ).`, + ); + + if (pn === 1) { + expect(stateVariables["/pp"].stateValues.text).contain( + `from the line in that template is: ( ${Pxs[tn - 1]}, ${Pys[tn - 1]} ).`, + ); + + if (cn === 1) { + expect(stateVariables["/pc"].stateValues.text).contain( + `from that point is ${Pxs[tn - 1]}.`, + ); + expect(stateVariables["/pc2"].stateValues.text).contain( + `from that point is ${Pxs[tn - 1]}.`, + ); + } else if (cn === 2) { + expect(stateVariables["/pc"].stateValues.text).contain( + `from that point is ${Pys[tn - 1]}.`, + ); + expect(stateVariables["/pc2"].stateValues.text).contain( + `from that point is ${Pys[tn - 1]}.`, + ); + } else { + expect(stateVariables["/pc"].stateValues.text).contain( + "from that point is .", + ); + expect(stateVariables["/pc2"].stateValues.text).contain( + "from that point is .", + ); + } + } else if (pn === 2) { + expect(stateVariables["/pp"].stateValues.text).contain( + `from the line in that template is: ( ${Qxs[tn - 1]}, ${Qys[tn - 1]} ).`, + ); + + if (cn === 1) { + expect(stateVariables["/pc"].stateValues.text).contain( + `from that point is ${Qxs[tn - 1]}.`, + ); + expect(stateVariables["/pc2"].stateValues.text).contain( + `from that point is ${Qxs[tn - 1]}.`, + ); + } else if (cn === 2) { + expect(stateVariables["/pc"].stateValues.text).contain( + `from that point is ${Qys[tn - 1]}.`, + ); + expect(stateVariables["/pc2"].stateValues.text).contain( + `from that point is ${Qys[tn - 1]}.`, + ); + } else { + expect(stateVariables["/pc"].stateValues.text).contain( + "from that point is .", + ); + expect(stateVariables["/pc2"].stateValues.text).contain( + "from that point is .", + ); + } + } else { + expect(stateVariables["/pp"].stateValues.text).contain( + "from the line in that template is: .", + ); + expect(stateVariables["/pc"].stateValues.text).contain( + "from that point is .", + ); + expect(stateVariables["/pc2"].stateValues.text).contain( + "from that point is .", + ); + } + } + } + + await check_items(2, 1, 1, 1); + + await updateMathInputValue({ latex: "2", componentName: "/tn", core }); + await check_items(2, 2, 1, 1); + + await updateMathInputValue({ latex: "3", componentName: "/tn", core }); + await check_items(2, 3, 1, 1); + + await updateMathInputValue({ latex: "4", componentName: "/n", core }); + await check_items(4, 3, 1, 1); + + await updateMathInputValue({ latex: "3", componentName: "/pn", core }); + await check_items(4, 3, 3, 1); + + await updateMathInputValue({ latex: "2", componentName: "/pn", core }); + await check_items(4, 3, 2, 1); + + await updateMathInputValue({ latex: "3", componentName: "/cn", core }); + await check_items(4, 3, 2, 3); + + await updateMathInputValue({ latex: "2", componentName: "/cn", core }); + await check_items(4, 3, 2, 2); + + await updateMathInputValue({ latex: "3", componentName: "/n", core }); + await check_items(3, 3, 2, 2); + + await updateMathInputValue({ latex: "1", componentName: "/n", core }); + await check_items(1, 3, 2, 2); + + await updateMathInputValue({ latex: "1", componentName: "/tn", core }); + await check_items(1, 1, 2, 2); + }); + + it("dot and array notation from group", async () => { + let core = await createTestCore({ + doenetML: ` + + x + copied will be blank + hello + copied will also be blank + (4,5) + +

A y and a word.

+
+ +

the math: $grp[1]

+

a blank: $grp[2]

+

the text: $grp[3]

+

another blank: $grp[4]

+

the point: $grp[5]

+

the point x: $grp[5].x

+

the line: $grp[6]

+

the line, point 1: $grp[6].points[1]

+

the line, point 2, y: $grp[6].points[2].y

+

math from p: $(grp[7]/m)

+

text from p: $(grp[7]/t)

+

nothing: $grp[8]

+

Prop fixed from group: $grp.fixed

+

Prop x from group: $grp.x

+ `, + }); + + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p1"].stateValues.text).eq("the math: x"); + expect(stateVariables["/p2"].stateValues.text).eq("a blank: "); + expect(stateVariables["/p3"].stateValues.text).eq("the text: hello"); + expect(stateVariables["/p4"].stateValues.text).eq("another blank: "); + expect(stateVariables["/p5"].stateValues.text).eq( + "the point: ( 4, 5 )", + ); + expect(stateVariables["/p6"].stateValues.text).eq("the point x: 4"); + expect(stateVariables["/p7"].stateValues.text).eq( + "the line: 0 = x - y - 1", + ); + expect(stateVariables["/p8"].stateValues.text).eq( + "the line, point 1: ( 10, 9 )", + ); + expect(stateVariables["/p9"].stateValues.text).eq( + "the line, point 2, y: 8", + ); + expect(stateVariables["/p10"].stateValues.text).eq("math from p: y"); + expect(stateVariables["/p11"].stateValues.text).eq("text from p: word"); + expect(stateVariables["/p12"].stateValues.text).eq("nothing: "); + expect(stateVariables["/p13"].stateValues.text).eq( + "Prop fixed from group: false, true, false, false, false", + ); + expect(stateVariables["/p14"].stateValues.text).eq( + "Prop x from group: x, 4", + ); + }); + + it("implicitProp from an input", async () => { + let core = await createTestCore({ + doenetML: ` + + +

$mi

+

$mi{simplify}

+

$mi

+

+

+

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + let macrom1Name = + stateVariables["/pmacro1"].activeChildren[0].componentName; + let macrom2Name = + stateVariables["/pmacro2"].activeChildren[0].componentName; + let copym1Name = + stateVariables["/pcopy1"].activeChildren[0].componentName; + let copym2Name = + stateVariables["/pcopy2"].activeChildren[0].componentName; + let copym3Name = + stateVariables["/pcopy3"].activeChildren[0].componentName; + let copymi4Name = + stateVariables["/pcopy4"].activeChildren[0].componentName; + + expect(stateVariables[macrom1Name].componentType).eq("math"); + expect(stateVariables[macrom2Name].componentType).eq("math"); + expect(stateVariables[copym1Name].componentType).eq("math"); + expect(stateVariables[copym2Name].componentType).eq("math"); + expect(stateVariables[copym3Name].componentType).eq("math"); + expect(stateVariables[copymi4Name].componentType).eq("mathInput"); + expect(stateVariables[macrom1Name].stateValues.value.tree).eqls([ + "+", + "x", + "x", + ]); + expect(stateVariables[macrom2Name].stateValues.value.tree).eqls([ + "*", + 2, + "x", + ]); + expect(stateVariables[copym1Name].stateValues.value.tree).eqls([ + "+", + "x", + "x", + ]); + expect(stateVariables[copym2Name].stateValues.value.tree).eqls([ + "*", + 2, + "x", + ]); + expect(stateVariables[copym3Name].stateValues.value.tree).eqls([ + "*", + 2, + "x", + ]); + expect(stateVariables[copymi4Name].stateValues.value.tree).eqls([ + "+", + "x", + "x", + ]); + }); + + async function test_implicit_prop_sampe_component_type_attributes(core) { + let stateVariables = await returnAllStateVariables(core); + + const simplifiedNames = [ + "/mimplicit1", + "/mimplicit2", + "/mimplicit3", + "/mnotimplicit1", + "/mnotimplicit2", + "/mnotimplicit3", + ]; + + for (let name of simplifiedNames) { + expect(stateVariables[name].stateValues.value.tree).eqls([ + "*", + 2, + "x", + ]); + } + + const nonsimplifiedNames = [ + "/mnotimplicit4", + "/mnotimplicit5", + "/mnotimplicit6", + ]; + + for (let name of nonsimplifiedNames) { + expect(stateVariables[name].stateValues.value.tree).eqls([ + "+", + "x", + "x", + ]); + } + + const xNames = ["/msubimplicit1", "/msubimplicit2", "/msubimplicit3"]; + + for (let name of xNames) { + expect(stateVariables[name].stateValues.value.tree).eqls("x"); + } + + const yzNames = ["/nnotimplicit1", "/nnotimplicit2"]; + + for (let name of yzNames) { + expect(stateVariables[name].stateValues.value.tree).eqls([ + "+", + "y", + "z", + ]); + } + + const yNames = ["/nsubimplicit1", "/nsubimplicit2"]; + + for (let name of yNames) { + expect(stateVariables[name].stateValues.value.tree).eqls("y"); + } + + expect(stateVariables["/mimplicit1"].activeChildren.length).eq(0); + expect(stateVariables["/mimplicit2"].activeChildren.length).eq(0); + expect(stateVariables["/mimplicit3"].activeChildren.length).eq(0); + expect(stateVariables["/mnotimplicit1"].activeChildren.length).eq(2); + expect(stateVariables["/mnotimplicit2"].activeChildren.length).eq(2); + expect(stateVariables["/mnotimplicit3"].activeChildren.length).eq(2); + expect(stateVariables["/mnotimplicit4"].activeChildren.length).eq(2); + expect(stateVariables["/mnotimplicit5"].activeChildren.length).eq(2); + expect(stateVariables["/mnotimplicit6"].activeChildren.length).eq(2); + expect(stateVariables["/msubimplicit1"].activeChildren.length).eq(0); + expect(stateVariables["/msubimplicit2"].activeChildren.length).eq(0); + expect(stateVariables["/msubimplicit3"].activeChildren.length).eq(0); + + expect(stateVariables["/nnotimplicit1"].activeChildren.length).eq(2); + expect(stateVariables["/nnotimplicit2"].activeChildren.length).eq(2); + expect(stateVariables["/nsubimplicit1"].activeChildren.length).eq(0); + expect(stateVariables["/nsubimplicit2"].activeChildren.length).eq(0); + } + + it("implicitProp with same componentType depend on attributes", async () => { + let core = await createTestCore({ + doenetML: ` + x+x + $m{name="mimplicit1"} + $m{name="mimplicit2" createComponentOfType="math"} + + $m{name="mnotimplicit1" newNamespace} + $m{name="mnotimplicit2" newNamespace createComponentOfType="math"} + + $m{name="mnotimplicit4" simplify="false"} + $m{name="mnotimplicit5" simplify="false" createComponentOfType="math"} + + + $(mnotimplicit2/msub{name="msubimplicit1"}) + $(mnotimplicit3/msub{name="msubimplicit2"}) + + + + y+z + $n{name="nnotimplicit1"} + + $(nnotimplicit2/nsub{name="nsubimplicit1"}) + + + + `, + }); + + await test_implicit_prop_sampe_component_type_attributes(core); + }); + + it("implicitProp with same componentType depend on attributes, subnames", async () => { + let core = await createTestCore({ + doenetML: ` + + + + 1 + + + $(map[1]/m{name="mimplicit1"}) + $(map[1]/m{name="mimplicit2" createComponentOfType="math"}) + + $(map[1]/m{name="mnotimplicit1" newNamespace}) + $(map[1]/m{name="mnotimplicit2" newNamespace createComponentOfType="math"}) + + $(map[1]/m{name="mnotimplicit4" simplify="false"}) + $(map[1]/m{name="mnotimplicit5" simplify="false" createComponentOfType="math"}) + + + $(mnotimplicit2/msub{name="msubimplicit1"}) + $(mnotimplicit3/msub{name="msubimplicit2"}) + + + + + 1 + + + $(map2[1]/n{name="nnotimplicit1"}) + + $(nnotimplicit2/nsub{name="nsubimplicit1"}) + + + + `, + }); + + await test_implicit_prop_sampe_component_type_attributes(core); + }); + + it("copies of composites ignore implicitProp", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + +

+ +

$col

+ +

$col

+ +

$g

+ +

$g

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + let [macromi1Name, macromi2Name] = stateVariables[ + "/pmacro" + ].activeChildren.map((x) => x.componentName); + let [copymi1Name, copymi2Name] = stateVariables[ + "/pcopy" + ].activeChildren.map((x) => x.componentName); + let [macromi1Name2, macromi2Name2] = stateVariables[ + "/pmacro2" + ].activeChildren + .filter((x) => x.componentName) + .map((x) => x.componentName); + let [copymi1Name2, copymi2Name2] = stateVariables[ + "/pcopy2" + ].activeChildren + .filter((x) => x.componentName) + .map((x) => x.componentName); + + expect(stateVariables[macromi1Name].componentType).eq("mathInput"); + expect(stateVariables[macromi2Name].componentType).eq("mathInput"); + expect(stateVariables[copymi1Name].componentType).eq("mathInput"); + expect(stateVariables[copymi2Name].componentType).eq("mathInput"); + expect(stateVariables[macromi1Name].stateValues.value.tree).eq("x"); + expect(stateVariables[macromi2Name].stateValues.value.tree).eq("y"); + expect(stateVariables[copymi1Name].stateValues.value.tree).eq("x"); + expect(stateVariables[copymi2Name].stateValues.value.tree).eq("y"); + expect(stateVariables[macromi1Name2].componentType).eq("mathInput"); + expect(stateVariables[macromi2Name2].componentType).eq("mathInput"); + expect(stateVariables[copymi1Name2].componentType).eq("mathInput"); + expect(stateVariables[copymi2Name2].componentType).eq("mathInput"); + expect(stateVariables[macromi1Name2].stateValues.value.tree).eq("x"); + expect(stateVariables[macromi2Name2].stateValues.value.tree).eq("y"); + expect(stateVariables[copymi1Name2].stateValues.value.tree).eq("x"); + expect(stateVariables[copymi2Name2].stateValues.value.tree).eq("y"); + }); + + it("copies of composites with subnames do not ignore implicitProp", async () => { + let core = await createTestCore({ + doenetML: ` + + + xy + + +

$map

+

$map

+ +

$map[1]$map[2]

+

+ +

$(map[1]/mi)$(map[2]/mi)

+

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + let [macromi1Name, macromi2Name] = stateVariables[ + "/pmacro" + ].activeChildren.map((x) => x.componentName); + let [copymi1Name, copymi2Name] = stateVariables[ + "/pcopy" + ].activeChildren.map((x) => x.componentName); + let [macroIndmi1Name, macroIndmi2Name] = stateVariables[ + "/pmacroInd" + ].activeChildren.map((x) => x.componentName); + let [copyIndmi1Name, copyIndmi2Name] = stateVariables[ + "/pmacroInd" + ].activeChildren.map((x) => x.componentName); + let [macroSubnamem1Name, macroSubnamem2Name] = stateVariables[ + "/pmacroSubname" + ].activeChildren.map((x) => x.componentName); + let [copySubnamem1Name, copySubnamem2Name] = stateVariables[ + "/pcopySubname" + ].activeChildren.map((x) => x.componentName); + + expect(stateVariables[macromi1Name].componentType).eq("mathInput"); + expect(stateVariables[macromi2Name].componentType).eq("mathInput"); + expect(stateVariables[copymi1Name].componentType).eq("mathInput"); + expect(stateVariables[copymi2Name].componentType).eq("mathInput"); + expect(stateVariables[macroIndmi1Name].componentType).eq("mathInput"); + expect(stateVariables[macroIndmi2Name].componentType).eq("mathInput"); + expect(stateVariables[copyIndmi1Name].componentType).eq("mathInput"); + expect(stateVariables[copyIndmi2Name].componentType).eq("mathInput"); + expect(stateVariables[macroSubnamem1Name].componentType).eq("math"); + expect(stateVariables[macroSubnamem2Name].componentType).eq("math"); + expect(stateVariables[copySubnamem1Name].componentType).eq("math"); + expect(stateVariables[copySubnamem2Name].componentType).eq("math"); + expect(stateVariables[macromi1Name].stateValues.value.tree).eq("x"); + expect(stateVariables[macromi2Name].stateValues.value.tree).eq("y"); + expect(stateVariables[copymi1Name].stateValues.value.tree).eq("x"); + expect(stateVariables[copymi2Name].stateValues.value.tree).eq("y"); + expect(stateVariables[macroIndmi1Name].stateValues.value.tree).eq("x"); + expect(stateVariables[macroIndmi2Name].stateValues.value.tree).eq("y"); + expect(stateVariables[copyIndmi1Name].stateValues.value.tree).eq("x"); + expect(stateVariables[copyIndmi2Name].stateValues.value.tree).eq("y"); + expect(stateVariables[macroSubnamem1Name].stateValues.value.tree).eq( + "x", + ); + expect(stateVariables[macroSubnamem2Name].stateValues.value.tree).eq( + "y", + ); + expect(stateVariables[copySubnamem1Name].stateValues.value.tree).eq( + "x", + ); + expect(stateVariables[copySubnamem2Name].stateValues.value.tree).eq( + "y", + ); + }); + + it("implicitProp with createComponentOfType", async () => { + let core = await createTestCore({ + doenetML: ` +

+ +

$mi{createComponentOfType='mathinput'}, $mi, $mi{createComponentOfType='math'}

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let mi3Name = stateVariables["/p2"].activeChildren[0].componentName; + let m2Name = stateVariables["/p2"].activeChildren[2].componentName; + let m3Name = stateVariables["/p2"].activeChildren[4].componentName; + + expect(stateVariables[m2Name].stateValues.value.tree).eq("\uff3f"); + expect(stateVariables[m3Name].stateValues.value.tree).eq("\uff3f"); + + // mathinputs change with immediate value + await updateMathInputImmediateValue({ + latex: "x", + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi2"].stateValues.rawRendererValue).eq("x"); + expect(stateVariables[mi3Name].stateValues.rawRendererValue).eq("x"); + expect(stateVariables["/m"].stateValues.value.tree).eq("\uff3f"); + expect(stateVariables[m2Name].stateValues.value.tree).eq("\uff3f"); + expect(stateVariables[m3Name].stateValues.value.tree).eq("\uff3f"); + + // maths change with value + await updateMathInputValueToImmediateValue({ + componentName: "/mi", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m"].stateValues.value.tree).eq("x"); + expect(stateVariables[m2Name].stateValues.value.tree).eq("x"); + expect(stateVariables[m3Name].stateValues.value.tree).eq("x"); + + // mathinputs change with immediate value + await updateMathInputImmediateValue({ + latex: "y", + componentName: "/mi2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.rawRendererValue).eq("y"); + expect(stateVariables[mi3Name].stateValues.rawRendererValue).eq("y"); + expect(stateVariables["/m"].stateValues.value.tree).eq("x"); + expect(stateVariables[m2Name].stateValues.value.tree).eq("x"); + expect(stateVariables[m3Name].stateValues.value.tree).eq("x"); + + // maths change with value + await updateMathInputValueToImmediateValue({ + componentName: "/mi2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m"].stateValues.value.tree).eq("y"); + expect(stateVariables[m2Name].stateValues.value.tree).eq("y"); + expect(stateVariables[m3Name].stateValues.value.tree).eq("y"); + + // mathinputs change with immediate value + await updateMathInputImmediateValue({ + latex: "z", + componentName: mi3Name, + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/mi"].stateValues.rawRendererValue).eq("z"); + expect(stateVariables["/mi2"].stateValues.rawRendererValue).eq("z"); + expect(stateVariables["/m"].stateValues.value.tree).eq("y"); + expect(stateVariables[m2Name].stateValues.value.tree).eq("y"); + expect(stateVariables[m3Name].stateValues.value.tree).eq("y"); + + // maths change with value + await updateMathInputValueToImmediateValue({ + componentName: mi3Name, + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/m"].stateValues.value.tree).eq("z"); + expect(stateVariables[m2Name].stateValues.value.tree).eq("z"); + expect(stateVariables[m3Name].stateValues.value.tree).eq("z"); + }); + + it("asList when copy array prop", async () => { + let core = await createTestCore({ + doenetML: ` + + yes + no + maybe + + +

Default: $ci.choiceTexts

+

No commas: $ci.choiceTexts{asList="false"}

+

With commas: $ci.choiceTexts{asList="true"}

+

+

+

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/default"].stateValues.text).eq( + "Default: yes, no, maybe", + ); + expect(stateVariables["/nocommas"].stateValues.text).eq( + "No commas: yesnomaybe", + ); + expect(stateVariables["/withcommas"].stateValues.text).eq( + "With commas: yes, no, maybe", + ); + expect(stateVariables["/default2"].stateValues.text).eq( + "Default: yes, no, maybe", + ); + expect(stateVariables["/nocommas2"].stateValues.text).eq( + "No commas: yesnomaybe", + ); + expect(stateVariables["/withcommas2"].stateValues.text).eq( + "With commas: yes, no, maybe", + ); + }); + + it("asList when copy array prop, multiple stacked props", async () => { + let core = await createTestCore({ + doenetML: ` + + +

Default: $l.points.x

+

No commas: $l.points.x{asList="false"}

+

With commas: $l.points.x{asList="true"}

+

+

+

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/default"].stateValues.text).eq("Default: 1, 3"); + expect(stateVariables["/nocommas"].stateValues.text).eq( + "No commas: 13", + ); + expect(stateVariables["/withcommas"].stateValues.text).eq( + "With commas: 1, 3", + ); + expect(stateVariables["/default2"].stateValues.text).eq( + "Default: 1, 3", + ); + expect(stateVariables["/nocommas2"].stateValues.text).eq( + "No commas: 13", + ); + expect(stateVariables["/withcommas2"].stateValues.text).eq( + "With commas: 1, 3", + ); + }); + + it("asList when copy array prop, aslist overrides", async () => { + let core = await createTestCore({ + doenetML: ` + + yes + no + maybe + + + +

Override no commas: $ci.choiceTexts{asList="false"}

+

Copy:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq( + "Override no commas: yes, no, maybe", + ); + expect(stateVariables["/p2"].stateValues.text).eq( + "Copy: yes, no, maybe", + ); + }); + + it("correctly wrap replacement changes when verifying to force component type", async () => { + let core = await createTestCore({ + doenetML: ` + 47 + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + const tiName = + stateVariables["/ans"].stateValues.inputChildren[0].componentName; + + expect(stateVariables["/num"].stateValues.value).eqls(NaN); + + await updateMathInputValue({ latex: "4", componentName: tiName, core }); + await core.requestAction({ + componentName: "/ans", + actionName: "submitAnswer", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/num"].stateValues.value).eq(4); + + await updateMathInputValue({ + latex: "47", + componentName: tiName, + core, + }); + await core.requestAction({ + componentName: "/ans", + actionName: "submitAnswer", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/num"].stateValues.value).eq(47); + }); + + it("copy of copy with new namespace, macros", async () => { + let core = await createTestCore({ + doenetML: ` + hello + +

copy with new namespace: $orig{name="cN" newnamespace}

+

copy of copy: $cN{name="cNc"}

+ +

copy of copy of copy: $cNc{name="cNcc"}

+

copy of copy of copy nn: $cNc{name="cNccN" newNamespace}

+ +

piece of copy: $(cN/t{name="cNt"})

+

piece of copy of copy: $(cNc/t{name="cNct"})

+ +

piece of copy of copy of copy: $(cNcc/t{name="cNcct"})

+

piece of copy of copy of copy nn: $(cNccN/t{name="cNccNt"})

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/orig"].componentType).eq("group"); + expect(stateVariables["/t"].stateValues.value).eq("hello"); + + expect(stateVariables["/cN"].componentType).eq("group"); + expect(stateVariables["/cN/t"].stateValues.value).eq("hello"); + expect(stateVariables["/cNt"].stateValues.value).eq("hello"); + + expect(stateVariables["/cNc"].componentType).eq("group"); + expect(stateVariables["/cNc/t"].stateValues.value).eq("hello"); + expect(stateVariables["/cNct"].stateValues.value).eq("hello"); + + expect(stateVariables["/cNcc"].componentType).eq("group"); + expect(stateVariables["/cNcc/t"].stateValues.value).eq("hello"); + expect(stateVariables["/cNcct"].stateValues.value).eq("hello"); + + expect(stateVariables["/cNccN"].componentType).eq("group"); + expect(stateVariables["/cNccN/t"].stateValues.value).eq("hello"); + expect(stateVariables["/cNccNt"].stateValues.value).eq("hello"); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/evaluate.test.ts b/packages/doenetml-worker/src/test/tagSpecific/evaluate.test.ts new file mode 100644 index 000000000..66b033413 --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/evaluate.test.ts @@ -0,0 +1,3815 @@ +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("Evaluate tag tests", async () => { + it("evaluate numeric and symbolic", async () => { + let core = await createTestCore({ + doenetML: ` +

Variable:

+

Function:

+

Input value:

+ + $formula + + $formula + +

Evaluate symbolic: + +

+ +

Evaluate symbolic using macro: $$f_symbolic($input)

+ +

Evaluated symbolic result again: $result_symbolic{name="result_symbolic3"}

+ + +

Evaluate numeric: + +

+ +

Evaluate numeric using macro: $$f_numeric($input)

+ + +

Evaluated numeric result again: $result_numeric{name="result_numeric3"}

+ + +

Force evaluate symbolic: + +

+ +

Force evaluate symbolic numeric function: + +

+ +

Force evaluate numeric: + +

+ +

Force evaluate numeric symbolic function: + +

+ + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/result_symbolic"].stateValues.value.tree).eqls([ + "apply", + "sin", + 0, + ]); + let result_symbolic2_name = + stateVariables["/result_symbolic2"].activeChildren[0].componentName; + expect( + stateVariables[result_symbolic2_name].stateValues.value.tree, + ).eqls(["apply", "sin", 0]); + expect(stateVariables["/result_symbolic3"].stateValues.value.tree).eqls( + ["apply", "sin", 0], + ); + expect(stateVariables["/result_numeric"].stateValues.value.tree).eq(0); + let result_numeric2_name = + stateVariables["/result_numeric2"].activeChildren[0].componentName; + expect(stateVariables[result_numeric2_name].stateValues.value.tree).eq( + 0, + ); + expect(stateVariables["/result_numeric3"].stateValues.value.tree).eq(0); + expect( + stateVariables["/result_force_symbolic"].stateValues.value.tree, + ).eqls(["apply", "sin", 0]); + expect( + stateVariables["/result_force_symbolic_numeric"].stateValues.value + .tree, + ).eqls(["apply", "sin", 0]); + expect( + stateVariables["/result_force_numeric"].stateValues.value.tree, + ).eq(0); + expect( + stateVariables["/result_force_numeric_symbolic"].stateValues.value + .tree, + ).eq(0); + + // evaluate at pi + await updateMathInputValue({ + latex: "\\pi", + componentName: "/input", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/result_symbolic"].stateValues.value.tree).eqls([ + "apply", + "sin", + "pi", + ]); + expect( + stateVariables[result_symbolic2_name].stateValues.value.tree, + ).eqls(["apply", "sin", "pi"]); + expect(stateVariables["/result_symbolic3"].stateValues.value.tree).eqls( + ["apply", "sin", "pi"], + ); + expect( + stateVariables["/result_numeric"].stateValues.value.tree, + ).closeTo(0, 1e-10); + expect( + stateVariables[result_numeric2_name].stateValues.value.tree, + ).closeTo(0, 1e-10); + expect( + stateVariables["/result_numeric3"].stateValues.value.tree, + ).closeTo(0, 1e-10); + expect( + stateVariables["/result_force_symbolic"].stateValues.value.tree, + ).eqls(["apply", "sin", "pi"]); + expect( + stateVariables["/result_force_symbolic_numeric"].stateValues.value + .tree, + ).eqls(["apply", "sin", "pi"]); + expect( + stateVariables["/result_force_numeric"].stateValues.value.tree, + ).closeTo(0, 1e-10); + expect( + stateVariables["/result_force_numeric_symbolic"].stateValues.value + .tree, + ).closeTo(0, 1e-10); + + // change variable + await updateMathInputValue({ + latex: "y", + componentName: "/variable", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/result_symbolic"].stateValues.value.tree).eqls([ + "apply", + "sin", + "x", + ]); + expect( + stateVariables[result_symbolic2_name].stateValues.value.tree, + ).eqls(["apply", "sin", "x"]); + expect(stateVariables["/result_symbolic3"].stateValues.value.tree).eqls( + ["apply", "sin", "x"], + ); + expect(stateVariables["/result_numeric"].stateValues.value.tree).eqls( + NaN, + ); + expect( + stateVariables[result_numeric2_name].stateValues.value.tree, + ).eqls(NaN); + expect(stateVariables["/result_numeric3"].stateValues.value.tree).eqls( + NaN, + ); + expect( + stateVariables["/result_force_symbolic"].stateValues.value.tree, + ).eqls(["apply", "sin", "x"]); + expect( + stateVariables["/result_force_symbolic_numeric"].stateValues.value + .tree, + ).eqls(["apply", "sin", "x"]); + expect( + stateVariables["/result_force_numeric"].stateValues.value.tree, + ).eqls(NaN); + expect( + stateVariables["/result_force_numeric_symbolic"].stateValues.value + .tree, + ).eqls(NaN); + + // change formula to match variable + await updateMathInputValue({ + latex: "\\sin(y)", + componentName: "/formula", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/result_symbolic"].stateValues.value.tree).eqls([ + "apply", + "sin", + "pi", + ]); + expect( + stateVariables[result_symbolic2_name].stateValues.value.tree, + ).eqls(["apply", "sin", "pi"]); + expect(stateVariables["/result_symbolic3"].stateValues.value.tree).eqls( + ["apply", "sin", "pi"], + ); + expect( + stateVariables["/result_numeric"].stateValues.value.tree, + ).closeTo(0, 1e-10); + expect( + stateVariables[result_numeric2_name].stateValues.value.tree, + ).closeTo(0, 1e-10); + expect( + stateVariables["/result_numeric3"].stateValues.value.tree, + ).closeTo(0, 1e-10); + expect( + stateVariables["/result_force_symbolic"].stateValues.value.tree, + ).eqls(["apply", "sin", "pi"]); + expect( + stateVariables["/result_force_symbolic_numeric"].stateValues.value + .tree, + ).eqls(["apply", "sin", "pi"]); + expect( + stateVariables["/result_force_numeric"].stateValues.value.tree, + ).closeTo(0, 1e-10); + expect( + stateVariables["/result_force_numeric_symbolic"].stateValues.value + .tree, + ).closeTo(0, 1e-10); + }); + + it("user-defined function", async () => { + let core = await createTestCore({ + doenetML: ` +

Choose variable for function: . + Let f($x) = . + Let u = . + Then f(u) = f($u) = $$f($u).

+ +

$fformula

+ + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/result"].stateValues.latex)).eq( + "f(u)=f(3v)=3av", + ); + + // change function + await updateMathInputValue({ + latex: "bx^2", + componentName: "/fformula", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/result"].stateValues.latex)).eq( + "f(u)=f(3v)=9bv^{2}", + ); + + // change u + await updateMathInputValue({ + latex: "cq^2", + componentName: "/u", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/result"].stateValues.latex)).eq( + "f(u)=f(cq^{2})=bc^{2}q^{4}", + ); + + // change variable + await updateMathInputValue({ + latex: "y", + componentName: "/x", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/result"].stateValues.latex)).eq( + "f(u)=f(cq^{2})=bx^{2}", + ); + + // change function to match variable + await updateMathInputValue({ + latex: "ay+by^2", + componentName: "/fformula", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/result"].stateValues.latex)).eq( + "f(u)=f(cq^{2})=acq^{2}+bc^{2}q^{4}", + ); + }); + + it("evaluate function when input is replaced", async () => { + // catch bug where child dependency was not recalculated + // when a skipComponentNames = true + // and the number of active children did not change + let core = await createTestCore({ + doenetML: ` + 1+u + + + 1 + +

+ + `, + }); + + // initial state + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/eval"].stateValues.value.tree).eq("_"); + + // submit answer + await updateMathInputValue({ + latex: "4", + componentName: "/mi", + core, + }); + await core.requestAction({ + componentName: "/ans1", + actionName: "submitAnswer", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/eval"].stateValues.value.tree).eqls([ + "+", + 1, + 4, + ]); + }); + + it("rounding on display", async () => { + let core = await createTestCore({ + doenetML: ` + 100sin(x) + 100sin(x) + 100sin(x) + 100sin(x) + +

Input:

+ +

+ + + + + $ef1{name="ef1a"} + $ef2{name="ef2a"} + $ef3{name="ef3a"} + $ef4{name="ef4a"} +

+ +

+ + + + + $ef1dg6{name="ef1dg6a"} + $ef2dg6{name="ef2dg6a"} + $ef3dg6{name="ef3dg6a"} + $ef4dg6{name="ef4dg6a"} +

+ +

+ + + + + $ef1dc6{name="ef1dc6a"} + $ef2dc6{name="ef2dc6a"} + $ef3dc6{name="ef3dc6a"} + $ef4dc6{name="ef4dc6a"} +

+ +

+ + + + + $ef1dsz{name="ef1dsza"} + $ef2dsz{name="ef2dsza"} + $ef3dsz{name="ef3dsza"} + $ef4dsz{name="ef4dsza"} +

+ +

+ $$f1($input) + $$f2($input) + $$f3($input) + $$f4($input) + $ef1m{name="ef1ma"} + $ef2m{name="ef2ma"} + $ef3m{name="ef3ma"} + $ef4m{name="ef4ma"} +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/ef1"].stateValues.latex)).eq( + "84.147", + ); + expect(cleanLatex(stateVariables["/ef2"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef3"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef4"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef1a"].stateValues.latex)).eq( + "84.147", + ); + expect(cleanLatex(stateVariables["/ef2a"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef3a"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef4a"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef1dg6"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef2dg6"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef3dg6"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef4dg6"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef1dg6a"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef2dg6a"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef3dg6a"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef4dg6a"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef1dc6"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef2dc6"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef3dc6"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef4dc6"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef1dc6a"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef2dc6a"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef3dc6a"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef4dc6a"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef1dsz"].stateValues.latex)).eq( + "84.147", + ); + expect(cleanLatex(stateVariables["/ef2dsz"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef3dsz"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef4dsz"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef1dsza"].stateValues.latex)).eq( + "84.147", + ); + expect(cleanLatex(stateVariables["/ef2dsza"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef3dsza"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef4dsza"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef1m"].stateValues.latex)).eq( + "84.147", + ); + expect(cleanLatex(stateVariables["/ef2m"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef3m"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef4m"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef1ma"].stateValues.latex)).eq( + "84.147", + ); + expect(cleanLatex(stateVariables["/ef2ma"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef3ma"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef4ma"].stateValues.latex)).eq( + "84.15", + ); + + await updateMathInputValue({ + latex: "\\pi", + componentName: "/input", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/ef1"].stateValues.latex).slice(0, 5), + ).eq(Math.sin(Math.PI).toString().slice(0, 5)); + expect(cleanLatex(stateVariables["/ef2"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef3"].stateValues.latex)).eq("0"); + expect( + cleanLatex(stateVariables["/ef4"].stateValues.latex).slice(0, 3), + ).eq(Math.sin(Math.PI).toString().slice(0, 3)); + expect( + cleanLatex(stateVariables["/ef1a"].stateValues.latex).slice(0, 5), + ).eq(Math.sin(Math.PI).toString().slice(0, 5)); + expect(cleanLatex(stateVariables["/ef2a"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef3a"].stateValues.latex)).eq("0"); + expect( + cleanLatex(stateVariables["/ef4a"].stateValues.latex).slice(0, 3), + ).eq(Math.sin(Math.PI).toString().slice(0, 3)); + expect( + cleanLatex(stateVariables["/ef1dg6"].stateValues.latex).slice(0, 6), + ).eq(Math.sin(Math.PI).toString().slice(0, 6)); + expect( + cleanLatex(stateVariables["/ef2dg6"].stateValues.latex).slice(0, 6), + ).eq(Math.sin(Math.PI).toString().slice(0, 6)); + expect(cleanLatex(stateVariables["/ef3dg6"].stateValues.latex)).eq("0"); + expect( + cleanLatex(stateVariables["/ef4dg6"].stateValues.latex).slice(0, 6), + ).eq(Math.sin(Math.PI).toString().slice(0, 6)); + expect( + cleanLatex(stateVariables["/ef1dg6a"].stateValues.latex).slice( + 0, + 6, + ), + ).eq(Math.sin(Math.PI).toString().slice(0, 6)); + expect( + cleanLatex(stateVariables["/ef2dg6a"].stateValues.latex).slice( + 0, + 6, + ), + ).eq(Math.sin(Math.PI).toString().slice(0, 6)); + expect(cleanLatex(stateVariables["/ef3dg6a"].stateValues.latex)).eq( + "0", + ); + expect( + cleanLatex(stateVariables["/ef4dg6a"].stateValues.latex).slice( + 0, + 6, + ), + ).eq(Math.sin(Math.PI).toString().slice(0, 6)); + expect(cleanLatex(stateVariables["/ef1dc6"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef2dc6"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef3dc6"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef4dc6"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef1dc6a"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/ef2dc6a"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/ef3dc6a"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/ef4dc6a"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/ef1dsz"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef2dsz"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef3dsz"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef4dsz"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef1dsza"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/ef2dsza"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/ef3dsza"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/ef4dsza"].stateValues.latex)).eq( + "0", + ); + expect( + cleanLatex(stateVariables["/ef1m"].stateValues.latex).slice(0, 6), + ).eq(Math.sin(Math.PI).toString().slice(0, 6)); + expect(cleanLatex(stateVariables["/ef2m"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef3m"].stateValues.latex)).eq("0"); + expect( + cleanLatex(stateVariables["/ef4m"].stateValues.latex).slice(0, 3), + ).eq(Math.sin(Math.PI).toString().slice(0, 3)); + expect( + cleanLatex(stateVariables["/ef1ma"].stateValues.latex).slice(0, 6), + ).eq(Math.sin(Math.PI).toString().slice(0, 6)); + expect(cleanLatex(stateVariables["/ef2ma"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef3ma"].stateValues.latex)).eq("0"); + expect( + cleanLatex(stateVariables["/ef4ma"].stateValues.latex).slice(0, 3), + ).eq(Math.sin(Math.PI).toString().slice(0, 3)); + }); + + it("rounding on display, overwrite on copy", async () => { + let core = await createTestCore({ + doenetML: ` + 100sin(x) + 100sin(x) + 100sin(x) + 100sin(x) + +

Input:

+ +

+ + + + + $ef1{name="ef1dg6" displayDigits="6"} + $ef2{name="ef2dg6" displayDigits="6"} + $ef3{name="ef3dg6" displayDigits="6"} + $ef4{name="ef4dg6" displayDigits="6"} + $ef1{name="ef1dc6" displayDecimals="6"} + $ef2{name="ef2dc6" displayDecimals="6"} + $ef3{name="ef3dc6" displayDecimals="6"} + $ef4{name="ef4dc6" displayDecimals="6"} + $ef1{name="ef1dsz" displaySmallAsZero="1E-13"} + $ef2{name="ef2dsz" displaySmallAsZero="1E-13"} + $ef3{name="ef3dsz" displaySmallAsZero="1E-13"} + $ef4{name="ef4dsz" displaySmallAsZero="1E-13"} + $ef1dc6{name="ef1dg6a" displayDigits="6"} + $ef2dc6{name="ef2dg6a" displayDigits="6"} + $ef3dc6{name="ef3dg6a" displayDigits="6"} + $ef4dc6{name="ef4dg6a" displayDigits="6"} + $ef1dg6{name="ef1dc6a" displayDecimals="6"} + $ef2dg6{name="ef2dc6a" displayDecimals="6"} + $ef3dg6{name="ef3dc6a" displayDecimals="6"} + $ef4dg6{name="ef4dc6a" displayDecimals="6"} +

+ +

+ + + + + $ef1dg6b{name="ef1dg8" displayDigits="8"} + $ef2dg6b{name="ef2dg8" displayDigits="8"} + $ef3dg6b{name="ef3dg8" displayDigits="8"} + $ef4dg6b{name="ef4dg8" displayDigits="8"} + $ef1dg6b{name="ef1dc6b" displayDecimals="6"} + $ef2dg6b{name="ef2dc6b" displayDecimals="6"} + $ef3dg6b{name="ef3dc6b" displayDecimals="6"} + $ef4dg6b{name="ef4dc6b" displayDecimals="6"} +

+ +

+ + + + + $ef1dc6c{name="ef1dc7" displayDecimals="7"} + $ef2dc6c{name="ef2dc7" displayDecimals="7"} + $ef3dc6c{name="ef3dc7" displayDecimals="7"} + $ef4dc6c{name="ef4dc7" displayDecimals="7"} + $ef1dc6c{name="ef1dg6c" displayDigits="6"} + $ef2dc6c{name="ef2dg6c" displayDigits="6"} + $ef3dc6c{name="ef3dg6c" displayDigits="6"} + $ef4dc6c{name="ef4dg6c" displayDigits="6"} +

+ +

+ + + + + $ef1dsza{name="ef1dsz0a" displaySmallAsZero="0"} + $ef2dsza{name="ef2dsz0a" displaySmallAsZero="0"} + $ef3dsza{name="ef3dsz0a" displaySmallAsZero="0"} + $ef4dsza{name="ef4dsz0a" displaySmallAsZero="0"} +

+ + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/ef1"].stateValues.latex)).eq( + "84.147", + ); + expect(cleanLatex(stateVariables["/ef2"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef3"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef4"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef1dg6"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef2dg6"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef3dg6"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef4dg6"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef1dg6a"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef2dg6a"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef3dg6a"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef4dg6a"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef1dg6b"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef2dg6b"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef3dg6b"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef4dg6b"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef1dg6c"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef2dg6c"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef3dg6c"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef4dg6c"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef1dc6"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef2dc6"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef3dc6"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef4dc6"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef1dc6a"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef2dc6a"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef3dc6a"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef4dc6a"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef1dc6b"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef2dc6b"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef3dc6b"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef4dc6b"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef1dc6c"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef2dc6c"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef3dc6c"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef4dc6c"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef1dg8"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef2dg8"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef3dg8"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef4dg8"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef1dc7"].stateValues.latex)).eq( + "84.1470985", + ); + expect(cleanLatex(stateVariables["/ef2dc7"].stateValues.latex)).eq( + "84.1470985", + ); + expect(cleanLatex(stateVariables["/ef3dc7"].stateValues.latex)).eq( + "84.1470985", + ); + expect(cleanLatex(stateVariables["/ef4dc7"].stateValues.latex)).eq( + "84.1470985", + ); + expect(cleanLatex(stateVariables["/ef1dsz"].stateValues.latex)).eq( + "84.147", + ); + expect(cleanLatex(stateVariables["/ef2dsz"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef3dsz"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef4dsz"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef1dsza"].stateValues.latex)).eq( + "84.147", + ); + expect(cleanLatex(stateVariables["/ef2dsza"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef3dsza"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef4dsza"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef1dsz0a"].stateValues.latex)).eq( + "84.147", + ); + expect(cleanLatex(stateVariables["/ef2dsz0a"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef3dsz0a"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef4dsz0a"].stateValues.latex)).eq( + "84.15", + ); + + await updateMathInputValue({ + latex: "\\pi", + componentName: "/input", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/ef1"].stateValues.latex).slice(0, 6), + ).eq(Math.sin(Math.PI).toString().slice(0, 6)); + expect(cleanLatex(stateVariables["/ef2"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef3"].stateValues.latex)).eq("0"); + expect( + cleanLatex(stateVariables["/ef4"].stateValues.latex).slice(0, 3), + ).eq(Math.sin(Math.PI).toString().slice(0, 3)); + expect( + cleanLatex(stateVariables["/ef1dg6"].stateValues.latex).slice(0, 6), + ).eq(Math.sin(Math.PI).toString().slice(0, 6)); + expect( + cleanLatex(stateVariables["/ef2dg6"].stateValues.latex).slice(0, 6), + ).eq(Math.sin(Math.PI).toString().slice(0, 6)); + expect(cleanLatex(stateVariables["/ef3dg6"].stateValues.latex)).eq("0"); + expect( + cleanLatex(stateVariables["/ef4dg6"].stateValues.latex).slice(0, 6), + ).eq(Math.sin(Math.PI).toString().slice(0, 6)); + expect( + cleanLatex(stateVariables["/ef1dg6a"].stateValues.latex).slice( + 0, + 6, + ), + ).eq(Math.sin(Math.PI).toString().slice(0, 6)); + expect( + cleanLatex(stateVariables["/ef2dg6a"].stateValues.latex).slice( + 0, + 6, + ), + ).eq(Math.sin(Math.PI).toString().slice(0, 6)); + expect(cleanLatex(stateVariables["/ef3dg6a"].stateValues.latex)).eq( + "0", + ); + expect( + cleanLatex(stateVariables["/ef4dg6a"].stateValues.latex).slice( + 0, + 6, + ), + ).eq(Math.sin(Math.PI).toString().slice(0, 6)); + expect( + cleanLatex(stateVariables["/ef1dg6b"].stateValues.latex).slice( + 0, + 6, + ), + ).eq(Math.sin(Math.PI).toString().slice(0, 6)); + expect( + cleanLatex(stateVariables["/ef2dg6b"].stateValues.latex).slice( + 0, + 6, + ), + ).eq(Math.sin(Math.PI).toString().slice(0, 6)); + expect(cleanLatex(stateVariables["/ef3dg6b"].stateValues.latex)).eq( + "0", + ); + expect( + cleanLatex(stateVariables["/ef4dg6b"].stateValues.latex).slice( + 0, + 6, + ), + ).eq(Math.sin(Math.PI).toString().slice(0, 6)); + expect( + cleanLatex(stateVariables["/ef1dg6c"].stateValues.latex).slice( + 0, + 6, + ), + ).eq(Math.sin(Math.PI).toString().slice(0, 6)); + expect( + cleanLatex(stateVariables["/ef2dg6c"].stateValues.latex).slice( + 0, + 6, + ), + ).eq(Math.sin(Math.PI).toString().slice(0, 6)); + expect(cleanLatex(stateVariables["/ef3dg6c"].stateValues.latex)).eq( + "0", + ); + expect( + cleanLatex(stateVariables["/ef4dg6c"].stateValues.latex).slice( + 0, + 6, + ), + ).eq(Math.sin(Math.PI).toString().slice(0, 6)); + expect(cleanLatex(stateVariables["/ef1dc6"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef2dc6"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef3dc6"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef4dc6"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef1dc6a"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/ef2dc6a"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/ef3dc6a"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/ef4dc6a"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/ef1dc6b"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/ef2dc6b"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/ef3dc6b"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/ef4dc6b"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/ef1dc6c"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/ef2dc6c"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/ef3dc6c"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/ef4dc6c"].stateValues.latex)).eq( + "0", + ); + expect( + cleanLatex(stateVariables["/ef1dg8"].stateValues.latex).slice(0, 8), + ).eq(Math.sin(Math.PI).toString().slice(0, 8)); + expect( + cleanLatex(stateVariables["/ef2dg8"].stateValues.latex).slice(0, 8), + ).eq(Math.sin(Math.PI).toString().slice(0, 8)); + expect(cleanLatex(stateVariables["/ef3dg8"].stateValues.latex)).eq("0"); + expect( + cleanLatex(stateVariables["/ef4dg8"].stateValues.latex).slice(0, 8), + ).eq(Math.sin(Math.PI).toString().slice(0, 8)); + expect(cleanLatex(stateVariables["/ef1dc7"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef2dc7"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef3dc7"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef4dc7"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef1dsz"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef2dsz"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef3dsz"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef4dsz"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef1dsza"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/ef2dsza"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/ef3dsza"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/ef4dsza"].stateValues.latex)).eq( + "0", + ); + expect( + cleanLatex(stateVariables["/ef1dsz0a"].stateValues.latex).slice( + 0, + 3, + ), + ).eq(Math.sin(Math.PI).toString().slice(0, 3)); + expect(cleanLatex(stateVariables["/ef2dsz0a"].stateValues.latex)).eq( + "0", + ); + expect( + cleanLatex(stateVariables["/ef3dsz0a"].stateValues.latex).slice( + 0, + 3, + ), + ).eq(Math.sin(Math.PI).toString().slice(0, 3)); + expect( + cleanLatex(stateVariables["/ef4dsz0a"].stateValues.latex).slice( + 0, + 3, + ), + ).eq(Math.sin(Math.PI).toString().slice(0, 3)); + }); + + it("rounding on display, ovewrite on copy functions", async () => { + let core = await createTestCore({ + doenetML: ` + + + 100sin(x) + + +

Input:

+ +

+ + + + + $ef1{name="ef1a"} + $ef2{name="ef2a"} + $ef3{name="ef3a"} + $ef4{name="ef4a"} +

+ +

+ + + + + $ef1dg6{name="ef1dg6a"} + $ef2dg6{name="ef2dg6a"} + $ef3dg6{name="ef3dg6a"} + $ef4dg6{name="ef4dg6a"} +

+ +

+ + + + + $ef1dc6{name="ef1dc6a"} + $ef2dc6{name="ef2dc6a"} + $ef3dc6{name="ef3dc6a"} + $ef4dc6{name="ef4dc6a"} +

+ +

+ + + + + $ef1dsz{name="ef1dsza"} + $ef2dsz{name="ef2dsza"} + $ef3dsz{name="ef3dsza"} + $ef4dsz{name="ef4dsza"} +

+ +

+ $$f1($input) + $$f2($input) + $$f3($input) + $$f4($input) + $ef1m{name="ef1ma"} + $ef2m{name="ef2ma"} + $ef3m{name="ef3ma"} + $ef4m{name="ef4ma"} +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/ef1"].stateValues.latex)).eq( + "84.147", + ); + expect(cleanLatex(stateVariables["/ef2"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef3"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef4"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef1a"].stateValues.latex)).eq( + "84.147", + ); + expect(cleanLatex(stateVariables["/ef2a"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef3a"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef4a"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef1dg6"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef2dg6"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef3dg6"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef4dg6"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef1dg6a"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef2dg6a"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef3dg6a"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef4dg6a"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef1dc6"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef2dc6"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef3dc6"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef4dc6"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef1dc6a"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef2dc6a"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef3dc6a"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef4dc6a"].stateValues.latex)).eq( + "84.147098", + ); + expect(cleanLatex(stateVariables["/ef1dsz"].stateValues.latex)).eq( + "84.147", + ); + expect(cleanLatex(stateVariables["/ef2dsz"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef3dsz"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef4dsz"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef1dsza"].stateValues.latex)).eq( + "84.147", + ); + expect(cleanLatex(stateVariables["/ef2dsza"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef3dsza"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef4dsza"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef1m"].stateValues.latex)).eq( + "84.147", + ); + expect(cleanLatex(stateVariables["/ef2m"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef3m"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef4m"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef1ma"].stateValues.latex)).eq( + "84.147", + ); + expect(cleanLatex(stateVariables["/ef2ma"].stateValues.latex)).eq( + "84.1471", + ); + expect(cleanLatex(stateVariables["/ef3ma"].stateValues.latex)).eq( + "84.15", + ); + expect(cleanLatex(stateVariables["/ef4ma"].stateValues.latex)).eq( + "84.15", + ); + + await updateMathInputValue({ + latex: "\\pi", + componentName: "/input", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/ef1"].stateValues.latex).slice(0, 5), + ).eq(Math.sin(Math.PI).toString().slice(0, 5)); + expect(cleanLatex(stateVariables["/ef2"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef3"].stateValues.latex)).eq("0"); + expect( + cleanLatex(stateVariables["/ef4"].stateValues.latex).slice(0, 3), + ).eq(Math.sin(Math.PI).toString().slice(0, 3)); + expect( + cleanLatex(stateVariables["/ef1a"].stateValues.latex).slice(0, 5), + ).eq(Math.sin(Math.PI).toString().slice(0, 5)); + expect(cleanLatex(stateVariables["/ef2a"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef3a"].stateValues.latex)).eq("0"); + expect( + cleanLatex(stateVariables["/ef4a"].stateValues.latex).slice(0, 3), + ).eq(Math.sin(Math.PI).toString().slice(0, 3)); + expect( + cleanLatex(stateVariables["/ef1dg6"].stateValues.latex).slice(0, 6), + ).eq(Math.sin(Math.PI).toString().slice(0, 6)); + expect( + cleanLatex(stateVariables["/ef2dg6"].stateValues.latex).slice(0, 6), + ).eq(Math.sin(Math.PI).toString().slice(0, 6)); + expect(cleanLatex(stateVariables["/ef3dg6"].stateValues.latex)).eq("0"); + expect( + cleanLatex(stateVariables["/ef4dg6"].stateValues.latex).slice(0, 6), + ).eq(Math.sin(Math.PI).toString().slice(0, 6)); + expect( + cleanLatex(stateVariables["/ef1dg6a"].stateValues.latex).slice( + 0, + 6, + ), + ).eq(Math.sin(Math.PI).toString().slice(0, 6)); + expect( + cleanLatex(stateVariables["/ef2dg6a"].stateValues.latex).slice( + 0, + 6, + ), + ).eq(Math.sin(Math.PI).toString().slice(0, 6)); + expect(cleanLatex(stateVariables["/ef3dg6a"].stateValues.latex)).eq( + "0", + ); + expect( + cleanLatex(stateVariables["/ef4dg6a"].stateValues.latex).slice( + 0, + 6, + ), + ).eq(Math.sin(Math.PI).toString().slice(0, 6)); + expect(cleanLatex(stateVariables["/ef1dc6"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef2dc6"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef3dc6"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef4dc6"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef1dc6a"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/ef2dc6a"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/ef3dc6a"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/ef4dc6a"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/ef1dsz"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef2dsz"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef3dsz"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef4dsz"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef1dsza"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/ef2dsza"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/ef3dsza"].stateValues.latex)).eq( + "0", + ); + expect(cleanLatex(stateVariables["/ef4dsza"].stateValues.latex)).eq( + "0", + ); + expect( + cleanLatex(stateVariables["/ef1m"].stateValues.latex).slice(0, 5), + ).eq(Math.sin(Math.PI).toString().slice(0, 5)); + expect(cleanLatex(stateVariables["/ef2m"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef3m"].stateValues.latex)).eq("0"); + expect( + cleanLatex(stateVariables["/ef4m"].stateValues.latex).slice(0, 3), + ).eq(Math.sin(Math.PI).toString().slice(0, 3)); + expect( + cleanLatex(stateVariables["/ef1ma"].stateValues.latex).slice(0, 5), + ).eq(Math.sin(Math.PI).toString().slice(0, 5)); + expect(cleanLatex(stateVariables["/ef2ma"].stateValues.latex)).eq("0"); + expect(cleanLatex(stateVariables["/ef3ma"].stateValues.latex)).eq("0"); + expect( + cleanLatex(stateVariables["/ef4ma"].stateValues.latex).slice(0, 3), + ).eq(Math.sin(Math.PI).toString().slice(0, 3)); + }); + + it("evaluate numeric and symbolic for function of two variables", async () => { + let core = await createTestCore({ + doenetML: ` +

Variable 1:

+

Variable 2:

+

Function:

+

Input 1 value:

+

Input 2 value:

+ + $formula + + $formula + +

Evaluate symbolic: + +

+ +

Evaluate symbolic using macro: $$f_symbolic($input1, $input2)

+ +

Evaluated symbolic result again: $result_symbolic{name="result_symbolic3"}

+ + +

Evaluate numeric: + +

+ +

Evaluate numeric using macro: $$f_numeric($input1, $input2)

+ +

Evaluated numeric result again: $result_numeric{name="result_numeric3"}

+ +

Force evaluate symbolic numeric function: + +

+ +

Force evaluate numeric symbolic function: + +

+ + + `, + }); + + // initial state + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/result_symbolic"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["+", 0, 0], + ]); + let result_symbolic2_name = + stateVariables["/result_symbolic2"].activeChildren[0].componentName; + expect( + stateVariables[result_symbolic2_name].stateValues.value.tree, + ).eqls(["apply", "sin", ["+", 0, 0]]); + expect(stateVariables["/result_symbolic3"].stateValues.value.tree).eqls( + ["apply", "sin", ["+", 0, 0]], + ); + expect(stateVariables["/result_numeric"].stateValues.value.tree).eq(0); + let result_numeric2_name = + stateVariables["/result_numeric2"].activeChildren[0].componentName; + expect(stateVariables[result_numeric2_name].stateValues.value.tree).eq( + 0, + ); + expect(stateVariables["/result_numeric3"].stateValues.value.tree).eq(0); + expect( + stateVariables["/result_force_symbolic_numeric"].stateValues.value + .tree, + ).eqls(["apply", "sin", ["+", 0, 0]]); + expect( + stateVariables["/result_force_numeric_symbolic"].stateValues.value + .tree, + ).eq(0); + + // evaluate at (pi, 2pi) + await updateMathInputValue({ + latex: "\\pi", + componentName: "/input1", + core, + }); + await updateMathInputValue({ + latex: "2\\pi", + componentName: "/input2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/result_symbolic"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["+", "pi", ["*", 2, "pi"]], + ]); + expect( + stateVariables[result_symbolic2_name].stateValues.value.tree, + ).eqls(["apply", "sin", ["+", "pi", ["*", 2, "pi"]]]); + expect(stateVariables["/result_symbolic3"].stateValues.value.tree).eqls( + ["apply", "sin", ["+", "pi", ["*", 2, "pi"]]], + ); + expect( + stateVariables["/result_numeric"].stateValues.value.tree, + ).closeTo(0, 1e-10); + expect( + stateVariables[result_numeric2_name].stateValues.value.tree, + ).closeTo(0, 1e-10); + expect( + stateVariables["/result_numeric3"].stateValues.value.tree, + ).closeTo(0, 1e-10); + expect( + stateVariables["/result_force_symbolic_numeric"].stateValues.value + .tree, + ).eqls(["apply", "sin", ["+", "pi", ["*", 2, "pi"]]]); + expect( + stateVariables["/result_force_numeric_symbolic"].stateValues.value + .tree, + ).closeTo(0, 1e-10); + + // change variable + await updateMathInputValue({ + latex: "u", + componentName: "/variable1", + core, + }); + await updateMathInputValue({ + latex: "v", + componentName: "/variable2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/result_symbolic"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["+", "x", "y"], + ]); + expect( + stateVariables[result_symbolic2_name].stateValues.value.tree, + ).eqls(["apply", "sin", ["+", "x", "y"]]); + expect(stateVariables["/result_symbolic3"].stateValues.value.tree).eqls( + ["apply", "sin", ["+", "x", "y"]], + ); + expect(stateVariables["/result_numeric"].stateValues.value.tree).eqls( + NaN, + ); + expect( + stateVariables[result_numeric2_name].stateValues.value.tree, + ).eqls(NaN); + expect(stateVariables["/result_numeric3"].stateValues.value.tree).eqls( + NaN, + ); + expect( + stateVariables["/result_force_symbolic_numeric"].stateValues.value + .tree, + ).eqls(["apply", "sin", ["+", "x", "y"]]); + expect( + stateVariables["/result_force_numeric_symbolic"].stateValues.value + .tree, + ).eqls(NaN); + + // change formula to use new variables + await updateMathInputValue({ + latex: "\\sin(u+v)", + componentName: "/formula", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/result_symbolic"].stateValues.value.tree).eqls([ + "apply", + "sin", + ["+", "pi", ["*", 2, "pi"]], + ]); + expect( + stateVariables[result_symbolic2_name].stateValues.value.tree, + ).eqls(["apply", "sin", ["+", "pi", ["*", 2, "pi"]]]); + expect(stateVariables["/result_symbolic3"].stateValues.value.tree).eqls( + ["apply", "sin", ["+", "pi", ["*", 2, "pi"]]], + ); + expect( + stateVariables["/result_numeric"].stateValues.value.tree, + ).closeTo(0, 1e-10); + expect( + stateVariables[result_numeric2_name].stateValues.value.tree, + ).closeTo(0, 1e-10); + expect( + stateVariables["/result_numeric3"].stateValues.value.tree, + ).closeTo(0, 1e-10); + expect( + stateVariables["/result_force_symbolic_numeric"].stateValues.value + .tree, + ).eqls(["apply", "sin", ["+", "pi", ["*", 2, "pi"]]]); + expect( + stateVariables["/result_force_numeric_symbolic"].stateValues.value + .tree, + ).closeTo(0, 1e-10); + }); + + it("function of multiple variables", async () => { + let core = await createTestCore({ + doenetML: ` +

Variables:

+

Function:

+

Input:

+ $variablesOrig + + $formula + +

Evaluate 1: + +

+ +

Evaluate 2: $$f($input)

+ +

Evaluate 3: $result1{name="result3"}

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/result1"].stateValues.value.tree).eqls(0); + let result2Name = + stateVariables["/result2"].activeChildren[0].componentName; + expect(stateVariables[result2Name].stateValues.value.tree).eqls(0); + expect(stateVariables["/result3"].stateValues.value.tree).eqls(0); + + // evaluate at (pi, pi/2) + await updateMathInputValue({ + latex: "(\\pi, \\pi/2)", + componentName: "/input", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/result1"].stateValues.value.tree).eqls(-1); + expect(stateVariables[result2Name].stateValues.value.tree).eqls(-1); + expect(stateVariables["/result3"].stateValues.value.tree).eqls(-1); + + // change variables to 3D + await updateMathInputValue({ + latex: "x,y,z", + componentName: "/variablesOrig", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/result1"].stateValues.value.tree).eqls("_"); + expect(stateVariables[result2Name].stateValues.value.tree).eqls("_"); + expect(stateVariables["/result3"].stateValues.value.tree).eqls("_"); + + // change input to 3D + await updateMathInputValue({ + latex: "(\\pi, \\pi/2,3)", + componentName: "/input", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/result1"].stateValues.value.tree).eqls(-1); + expect(stateVariables[result2Name].stateValues.value.tree).eqls(-1); + expect(stateVariables["/result3"].stateValues.value.tree).eqls(-1); + + // change formula to use all variables + await updateMathInputValue({ + latex: "z\\sin(x+y)", + componentName: "/formula", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/result1"].stateValues.value.tree).eqls(-3); + expect(stateVariables[result2Name].stateValues.value.tree).eqls(-3); + expect(stateVariables["/result3"].stateValues.value.tree).eqls(-3); + + // add fourth variable to formula + await updateMathInputValue({ + latex: "z\\sin(x+y/w)", + componentName: "/formula", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/result1"].stateValues.value.tree).eqls([ + "*", + 3, + ["apply", "sin", ["+", "pi", ["/", "pi", ["*", 2, "w"]]]], + ]); + expect(stateVariables[result2Name].stateValues.value.tree).eqls([ + "*", + 3, + ["apply", "sin", ["+", "pi", ["/", "pi", ["*", 2, "w"]]]], + ]); + expect(stateVariables["/result3"].stateValues.value.tree).eqls([ + "*", + 3, + ["apply", "sin", ["+", "pi", ["/", "pi", ["*", 2, "w"]]]], + ]); + + // add 4th input + await updateMathInputValue({ + latex: "(\\pi, \\pi/2,3,3)", + componentName: "/input", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/result1"].stateValues.value.tree).eqls("_"); + expect(stateVariables[result2Name].stateValues.value.tree).eqls("_"); + expect(stateVariables["/result3"].stateValues.value.tree).eqls("_"); + + // add 4th variable + await updateMathInputValue({ + latex: "x,y,z,w", + componentName: "/variablesOrig", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/result1"].stateValues.value.tree).eqls([ + "/", + -3, + 2, + ]); + expect(stateVariables[result2Name].stateValues.value.tree).eqls([ + "/", + -3, + 2, + ]); + expect(stateVariables["/result3"].stateValues.value.tree).eqls([ + "/", + -3, + 2, + ]); + }); + + it("different input forms for function of two variables", async () => { + let core = await createTestCore({ + doenetML: ` + x^2/y^3 +

Input as vector:

+

Input as list:

+ $input2Orig + + + + + + + +

Separate inputs: +

+ + +

Evaluate 1a: + +

+

Evaluate 1b: $$f($input1)

+ +

Evaluate 2a: + +

+

Evaluate 2b: $$f($input2)

+ +

Evaluate 3a: + +

+

Evaluate 3b: $$f($input3)

+ +

Evaluate 4a: + +

+

Evaluate 4b: $$f($input4a,$input4b)

+

Evaluate 4c: $$f($input4a, $input4b)

+ +

Evaluate 5a: + +

+

Evaluate 5b: $$f(($input4a,$input4b))

+

Evaluate 5c: $$f(($input4a, $input4b))

+

Evaluate 5d: + +

+ +

Evaluate 6a: + +

+

Evaluate 6b: $$f(2,3)

+

Evaluate 6c: $$f(2, 3)

+ +

Evaluate 7a: + +

+

Evaluate 7b: $$f((2,3))

+

Evaluate 7c: $$f((2, 3))

+

Evaluate 7d: + +

+ + `, + }); + + // initial state + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/result1a"].stateValues.value.tree).eqls([ + "/", + 4, + 27, + ]); + expect( + stateVariables[ + stateVariables["/result1b"].activeChildren[0].componentName + ].stateValues.value.tree, + ).eqls(["/", 4, 27]); + expect(stateVariables["/result2a"].stateValues.value.tree).eqls([ + "/", + 4, + 27, + ]); + expect( + stateVariables[ + stateVariables["/result2b"].activeChildren[0].componentName + ].stateValues.value.tree, + ).eqls(["/", 4, 27]); + expect(stateVariables["/result3a"].stateValues.value.tree).eqls([ + "/", + 4, + 27, + ]); + expect( + stateVariables[ + stateVariables["/result3b"].activeChildren[0].componentName + ].stateValues.value.tree, + ).eqls(["/", 4, 27]); + expect(stateVariables["/result4a"].stateValues.value.tree).eqls([ + "/", + 4, + 27, + ]); + expect( + stateVariables[ + stateVariables["/result4b"].activeChildren[0].componentName + ].stateValues.value.tree, + ).eqls(["/", 4, 27]); + expect( + stateVariables[ + stateVariables["/result4c"].activeChildren[0].componentName + ].stateValues.value.tree, + ).eqls(["/", 4, 27]); + expect(stateVariables["/result5a"].stateValues.value.tree).eqls([ + "/", + 4, + 27, + ]); + expect( + stateVariables[ + stateVariables["/result5b"].activeChildren[0].componentName + ].stateValues.value.tree, + ).eqls(["/", 4, 27]); + expect( + stateVariables[ + stateVariables["/result5c"].activeChildren[0].componentName + ].stateValues.value.tree, + ).eqls(["/", 4, 27]); + expect(stateVariables["/result5d"].stateValues.value.tree).eqls([ + "/", + 4, + 27, + ]); + expect(stateVariables["/result6a"].stateValues.value.tree).eqls([ + "/", + 4, + 27, + ]); + expect( + stateVariables[ + stateVariables["/result6b"].activeChildren[0].componentName + ].stateValues.value.tree, + ).eqls(["/", 4, 27]); + expect( + stateVariables[ + stateVariables["/result6c"].activeChildren[0].componentName + ].stateValues.value.tree, + ).eqls(["/", 4, 27]); + expect(stateVariables["/result7a"].stateValues.value.tree).eqls([ + "/", + 4, + 27, + ]); + expect( + stateVariables[ + stateVariables["/result7b"].activeChildren[0].componentName + ].stateValues.value.tree, + ).eqls(["/", 4, 27]); + expect( + stateVariables[ + stateVariables["/result7c"].activeChildren[0].componentName + ].stateValues.value.tree, + ).eqls(["/", 4, 27]); + expect(stateVariables["/result7d"].stateValues.value.tree).eqls([ + "/", + 4, + 27, + ]); + + // change inputs, use altvector + await updateMathInputValue({ + latex: "\\langle -3,5\\rangle", + componentName: "/input1", + core, + }); + await updateMathInputValue({ + latex: "-3,5", + componentName: "/input2Orig", + core, + }); + await updateMathInputValue({ + latex: "-3", + componentName: "/input4a", + core, + }); + await updateMathInputValue({ + latex: "5", + componentName: "/input4b", + core, + }); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/A", + args: { x: -3, y: 7 }, + event: null, + }); + await core.requestAction({ + actionName: "movePoint", + componentName: "/B", + args: { x: 5, y: -9 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/result1a"].stateValues.value.tree).eqls([ + "/", + 9, + 125, + ]); + expect( + stateVariables[ + stateVariables["/result1b"].activeChildren[0].componentName + ].stateValues.value.tree, + ).eqls(["/", 9, 125]); + expect(stateVariables["/result2a"].stateValues.value.tree).eqls([ + "/", + 9, + 125, + ]); + expect( + stateVariables[ + stateVariables["/result2b"].activeChildren[0].componentName + ].stateValues.value.tree, + ).eqls(["/", 9, 125]); + expect(stateVariables["/result3a"].stateValues.value.tree).eqls([ + "/", + 9, + 125, + ]); + expect( + stateVariables[ + stateVariables["/result3b"].activeChildren[0].componentName + ].stateValues.value.tree, + ).eqls(["/", 9, 125]); + expect(stateVariables["/result4a"].stateValues.value.tree).eqls([ + "/", + 9, + 125, + ]); + expect( + stateVariables[ + stateVariables["/result4b"].activeChildren[0].componentName + ].stateValues.value.tree, + ).eqls(["/", 9, 125]); + expect( + stateVariables[ + stateVariables["/result4c"].activeChildren[0].componentName + ].stateValues.value.tree, + ).eqls(["/", 9, 125]); + expect(stateVariables["/result5a"].stateValues.value.tree).eqls([ + "/", + 9, + 125, + ]); + expect( + stateVariables[ + stateVariables["/result5b"].activeChildren[0].componentName + ].stateValues.value.tree, + ).eqls(["/", 9, 125]); + expect( + stateVariables[ + stateVariables["/result5c"].activeChildren[0].componentName + ].stateValues.value.tree, + ).eqls(["/", 9, 125]); + expect(stateVariables["/result5d"].stateValues.value.tree).eqls([ + "/", + 9, + 125, + ]); + }); + + it("evaluate numeric and symbolic for vector-valued function of two variables", async () => { + let core = await createTestCore({ + doenetML: ` +

Variable 1:

+

Variable 2:

+

Function:

+

Input 1 value:

+

Input 2 value:

+ + $formula + + $formula + +

Evaluate symbolic: + +

+ +

Evaluate symbolic using macro: $$f_symbolic($input1, $input2)

+ +

Evaluated symbolic result again: $result_symbolic{name="result_symbolic3"}

+ + +

Evaluate numeric: + +

+ +

Evaluate numeric using macro: $$f_numeric($input1, $input2)

+ +

Evaluated numeric result again: $result_numeric{name="result_numeric3"}

+ +

Force evaluate symbolic numeric function: + +

+ +

Force evaluate numeric symbolic function: + +

+ + + `, + }); + + // initial state + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/result_symbolic"].stateValues.value.tree).eqls([ + "vector", + ["apply", "sin", 0], + ["apply", "cos", 0], + ]); + let result_symbolic2_name = + stateVariables["/result_symbolic2"].activeChildren[0].componentName; + expect( + stateVariables[result_symbolic2_name].stateValues.value.tree, + ).eqls(["vector", ["apply", "sin", 0], ["apply", "cos", 0]]); + expect(stateVariables["/result_symbolic3"].stateValues.value.tree).eqls( + ["vector", ["apply", "sin", 0], ["apply", "cos", 0]], + ); + expect(stateVariables["/result_numeric"].stateValues.value.tree).eqls([ + "vector", + 0, + 1, + ]); + let result_numeric2_name = + stateVariables["/result_numeric2"].activeChildren[0].componentName; + expect( + stateVariables[result_numeric2_name].stateValues.value.tree, + ).eqls(["vector", 0, 1]); + expect(stateVariables["/result_numeric3"].stateValues.value.tree).eqls([ + "vector", + 0, + 1, + ]); + expect( + stateVariables["/result_force_symbolic_numeric"].stateValues.value + .tree, + ).eqls(["vector", ["apply", "sin", 0], ["apply", "cos", 0]]); + expect( + stateVariables["/result_force_numeric_symbolic"].stateValues.value + .tree, + ).eqls(["vector", 0, 1]); + + // evaluate at (pi, 2pi) + await updateMathInputValue({ + latex: "\\pi", + componentName: "/input1", + core, + }); + await updateMathInputValue({ + latex: "2\\pi", + componentName: "/input2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/result_symbolic"].stateValues.value.tree).eqls([ + "vector", + ["apply", "sin", ["+", "pi", ["*", 2, "pi"]]], + ["apply", "cos", ["+", "pi", ["*", -2, "pi"]]], + ]); + expect( + stateVariables[result_symbolic2_name].stateValues.value.tree, + ).eqls([ + "vector", + ["apply", "sin", ["+", "pi", ["*", 2, "pi"]]], + ["apply", "cos", ["+", "pi", ["*", -2, "pi"]]], + ]); + expect(stateVariables["/result_symbolic3"].stateValues.value.tree).eqls( + [ + "vector", + ["apply", "sin", ["+", "pi", ["*", 2, "pi"]]], + ["apply", "cos", ["+", "pi", ["*", -2, "pi"]]], + ], + ); + expect( + stateVariables["/result_numeric"].stateValues.value.tree.map((x) => + typeof x === "number" && me.math.round(x, 10) === 0 ? 0 : x, + ), + ).eqls(["vector", 0, -1]); + expect( + stateVariables[result_numeric2_name].stateValues.value.tree.map( + (x) => + typeof x === "number" && me.math.round(x, 10) === 0 ? 0 : x, + ), + ).eqls(["vector", 0, -1]); + expect( + stateVariables["/result_numeric3"].stateValues.value.tree.map( + (x) => + typeof x === "number" && me.math.round(x, 10) === 0 ? 0 : x, + ), + ).eqls(["vector", 0, -1]); + expect( + stateVariables["/result_force_symbolic_numeric"].stateValues.value + .tree, + ).eqls([ + "vector", + ["apply", "sin", ["+", "pi", ["*", 2, "pi"]]], + ["apply", "cos", ["+", "pi", ["*", -2, "pi"]]], + ]); + expect( + stateVariables[ + "/result_force_numeric_symbolic" + ].stateValues.value.tree.map((x) => + typeof x === "number" && me.math.round(x, 10) === 0 ? 0 : x, + ), + ).eqls(["vector", 0, -1]); + + // change variable + await updateMathInputValue({ + latex: "u", + componentName: "/variable1", + core, + }); + await updateMathInputValue({ + latex: "v", + componentName: "/variable2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/result_symbolic"].stateValues.value.tree).eqls([ + "vector", + ["apply", "sin", ["+", "x", "y"]], + ["apply", "cos", ["+", "x", ["-", "y"]]], + ]); + expect( + stateVariables[result_symbolic2_name].stateValues.value.tree, + ).eqls([ + "vector", + ["apply", "sin", ["+", "x", "y"]], + ["apply", "cos", ["+", "x", ["-", "y"]]], + ]); + expect(stateVariables["/result_symbolic3"].stateValues.value.tree).eqls( + [ + "vector", + ["apply", "sin", ["+", "x", "y"]], + ["apply", "cos", ["+", "x", ["-", "y"]]], + ], + ); + expect( + stateVariables["/result_numeric"].stateValues.value.tree[1], + ).eqls(NaN); + expect( + stateVariables["/result_numeric"].stateValues.value.tree[2], + ).eqls(NaN); + expect( + stateVariables[result_numeric2_name].stateValues.value.tree[1], + ).eqls(NaN); + expect( + stateVariables[result_numeric2_name].stateValues.value.tree[2], + ).eqls(NaN); + expect( + stateVariables["/result_numeric3"].stateValues.value.tree[1], + ).eqls(NaN); + expect( + stateVariables["/result_numeric3"].stateValues.value.tree[2], + ).eqls(NaN); + expect( + stateVariables["/result_force_symbolic_numeric"].stateValues.value + .tree, + ).eqls([ + "vector", + ["apply", "sin", ["+", "x", "y"]], + ["apply", "cos", ["+", "x", ["-", "y"]]], + ]); + expect( + stateVariables["/result_force_numeric_symbolic"].stateValues.value + .tree[1], + ).eqls(NaN); + expect( + stateVariables["/result_force_numeric_symbolic"].stateValues.value + .tree[2], + ).eqls(NaN); + + // change formula to use new variables + await updateMathInputValue({ + latex: "(\\sin(u+v), \\cos(u-v))", + componentName: "/formula", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/result_symbolic"].stateValues.value.tree).eqls([ + "vector", + ["apply", "sin", ["+", "pi", ["*", 2, "pi"]]], + ["apply", "cos", ["+", "pi", ["*", -2, "pi"]]], + ]); + expect( + stateVariables[result_symbolic2_name].stateValues.value.tree, + ).eqls([ + "vector", + ["apply", "sin", ["+", "pi", ["*", 2, "pi"]]], + ["apply", "cos", ["+", "pi", ["*", -2, "pi"]]], + ]); + expect(stateVariables["/result_symbolic3"].stateValues.value.tree).eqls( + [ + "vector", + ["apply", "sin", ["+", "pi", ["*", 2, "pi"]]], + ["apply", "cos", ["+", "pi", ["*", -2, "pi"]]], + ], + ); + expect( + stateVariables["/result_numeric"].stateValues.value.tree.map((x) => + typeof x === "number" && me.math.round(x, 10) === 0 ? 0 : x, + ), + ).eqls(["vector", 0, -1]); + expect( + stateVariables[result_numeric2_name].stateValues.value.tree.map( + (x) => + typeof x === "number" && me.math.round(x, 10) === 0 ? 0 : x, + ), + ).eqls(["vector", 0, -1]); + expect( + stateVariables["/result_numeric3"].stateValues.value.tree.map( + (x) => + typeof x === "number" && me.math.round(x, 10) === 0 ? 0 : x, + ), + ).eqls(["vector", 0, -1]); + expect( + stateVariables["/result_force_symbolic_numeric"].stateValues.value + .tree, + ).eqls([ + "vector", + ["apply", "sin", ["+", "pi", ["*", 2, "pi"]]], + ["apply", "cos", ["+", "pi", ["*", -2, "pi"]]], + ]); + expect( + stateVariables[ + "/result_force_numeric_symbolic" + ].stateValues.value.tree.map((x) => + typeof x === "number" && me.math.round(x, 10) === 0 ? 0 : x, + ), + ).eqls(["vector", 0, -1]); + }); + + it("vector-valued function of multiple variables", async () => { + let core = await createTestCore({ + doenetML: ` +

Variables:

+

Function:

+

Input:

+ $variablesOrig + + $formula + +

Evaluate 1: + +

+ +

Evaluate 2: $$f($input)

+ +

Evaluate 3: $result1{name="result3"}

+ `, + }); + + // initial state + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/f"].stateValues.numInputs).eq(2); + expect(stateVariables["/f"].stateValues.numOutputs).eq(2); + expect(stateVariables["/result1"].stateValues.value.tree).eqls([ + "vector", + 0, + 0, + ]); + let result2Name = + stateVariables["/result2"].activeChildren[0].componentName; + expect(stateVariables[result2Name].stateValues.value.tree).eqls([ + "vector", + 0, + 0, + ]); + expect(stateVariables["/result3"].stateValues.value.tree).eqls([ + "vector", + 0, + 0, + ]); + + // evaluate at (7,3) + await updateMathInputValue({ + latex: "(7,3)", + componentName: "/input", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/f"].stateValues.numInputs).eq(2); + expect(stateVariables["/f"].stateValues.numOutputs).eq(2); + expect(stateVariables["/result1"].stateValues.value.tree).eqls([ + "vector", + 10, + 4, + ]); + expect(stateVariables[result2Name].stateValues.value.tree).eqls([ + "vector", + 10, + 4, + ]); + expect(stateVariables["/result3"].stateValues.value.tree).eqls([ + "vector", + 10, + 4, + ]); + + // change variables to 3D + await updateMathInputValue({ + latex: "x,y,z", + componentName: "/variablesOrig", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/f"].stateValues.numInputs).eq(3); + expect(stateVariables["/f"].stateValues.numOutputs).eq(2); + expect(stateVariables["/result1"].stateValues.value.tree).eqls("_"); + expect(stateVariables[result2Name].stateValues.value.tree).eqls("_"); + expect(stateVariables["/result3"].stateValues.value.tree).eqls("_"); + + // change input to 3D + await updateMathInputValue({ + latex: "(7,3,2)", + componentName: "/input", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/f"].stateValues.numInputs).eq(3); + expect(stateVariables["/f"].stateValues.numOutputs).eq(2); + expect(stateVariables["/result1"].stateValues.value.tree).eqls([ + "vector", + 10, + 4, + ]); + expect(stateVariables[result2Name].stateValues.value.tree).eqls([ + "vector", + 10, + 4, + ]); + expect(stateVariables["/result3"].stateValues.value.tree).eqls([ + "vector", + 10, + 4, + ]); + + // change formula to use all variables + await updateMathInputValue({ + latex: "(zx+y, x-yz)", + componentName: "/formula", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/f"].stateValues.numInputs).eq(3); + expect(stateVariables["/f"].stateValues.numOutputs).eq(2); + expect(stateVariables["/result1"].stateValues.value.tree).eqls([ + "vector", + 17, + 1, + ]); + expect(stateVariables[result2Name].stateValues.value.tree).eqls([ + "vector", + 17, + 1, + ]); + expect(stateVariables["/result3"].stateValues.value.tree).eqls([ + "vector", + 17, + 1, + ]); + + // add third dimension + await updateMathInputValue({ + latex: "(zx+y, x-yz,xyz)", + componentName: "/formula", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/f"].stateValues.numInputs).eq(3); + expect(stateVariables["/f"].stateValues.numOutputs).eq(3); + expect(stateVariables["/result1"].stateValues.value.tree).eqls([ + "vector", + 17, + 1, + 42, + ]); + expect(stateVariables[result2Name].stateValues.value.tree).eqls([ + "vector", + 17, + 1, + 42, + ]); + expect(stateVariables["/result3"].stateValues.value.tree).eqls([ + "vector", + 17, + 1, + 42, + ]); + + // add fourth variable and 4th dimension to formula + await updateMathInputValue({ + latex: "(zx+y, x-yz,xyzw,w)", + componentName: "/formula", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/f"].stateValues.numInputs).eq(3); + expect(stateVariables["/f"].stateValues.numOutputs).eq(4); + expect(stateVariables["/result1"].stateValues.value.tree).eqls([ + "vector", + 17, + 1, + ["*", 42, "w"], + "w", + ]); + expect(stateVariables[result2Name].stateValues.value.tree).eqls([ + "vector", + 17, + 1, + ["*", 42, "w"], + "w", + ]); + expect(stateVariables["/result3"].stateValues.value.tree).eqls([ + "vector", + 17, + 1, + ["*", 42, "w"], + "w", + ]); + + // add 4th input + await updateMathInputValue({ + latex: "(7,3,2,5)", + componentName: "/input", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/result1"].stateValues.value.tree).eqls("_"); + expect(stateVariables[result2Name].stateValues.value.tree).eqls("_"); + expect(stateVariables["/result3"].stateValues.value.tree).eqls("_"); + + // add 4th variable + await updateMathInputValue({ + latex: "x,y,z,w", + componentName: "/variablesOrig", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/result1"].stateValues.value.tree).eqls([ + "vector", + 17, + 1, + 210, + 5, + ]); + expect(stateVariables[result2Name].stateValues.value.tree).eqls([ + "vector", + 17, + 1, + 210, + 5, + ]); + expect(stateVariables["/result3"].stateValues.value.tree).eqls([ + "vector", + 17, + 1, + 210, + 5, + ]); + }); + + it("change variables of symbolic function", async () => { + let core = await createTestCore({ + doenetML: ` +

f: st^2

+

g: $f.formula

+ +

f(u, v+w) = $$f(u, v+w)

+

f(a+b, c) = $$f(a+b, c)

+

g(u, v+w) = $$g(u, v+w)

+

g(a+b, c) = $$g(a+b, c)

+ + `, + }); + + // initial state + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pf1"].stateValues.text).eq( + "f(u, v+w) = u v² + 2 u v w + u w²", + ); + expect(stateVariables["/pf2"].stateValues.text).eq( + "f(a+b, c) = a c² + b c²", + ); + expect(stateVariables["/pg1"].stateValues.text).eq( + "g(u, v+w) = v u² + w u²", + ); + expect(stateVariables["/pg2"].stateValues.text).eq( + "g(a+b, c) = c a² + 2 a b c + c b²", + ); + }); + + it("change variables of numeric function", async () => { + let core = await createTestCore({ + doenetML: ` +

f: st^2

+

g: $f.formula

+ +

f(2, -3) = $$f(2, -3)

+

g(2, -3) = $$g(2, -3)

+ + `, + }); + + // initial state + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pf"].stateValues.text).eq("f(2, -3) = 18"); + expect(stateVariables["/pg"].stateValues.text).eq("g(2, -3) = -12"); + }); + + it("change variables of interpolated function", async () => { + let core = await createTestCore({ + doenetML: ` +

f:

+

g: $f

+ +

f(3) = $$f(3)

+

f(4) = $$f(4)

+

f(5) = $$f(5)

+

g(3) = $$g(3)

+

g(4) = $$g(4)

+

g(5) = $$g(5)

+ + `, + }); + + // initial state + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pf1"].stateValues.text).eq("f(3) = 4"); + expect(stateVariables["/pf2"].stateValues.text).eq("f(4) = 3"); + expect(stateVariables["/pf3"].stateValues.text).eq("f(5) = 0"); + expect(stateVariables["/pg1"].stateValues.text).eq("g(3) = 4"); + expect(stateVariables["/pg2"].stateValues.text).eq("g(4) = 3"); + expect(stateVariables["/pg3"].stateValues.text).eq("g(5) = 0"); + }); + + it("evaluate at asymptotes", async () => { + let core = await createTestCore({ + doenetML: ` +

f1: 1/x

+

f2: 1/(-x)

+

f3: -1/x

+

f4: -1/(-x)

+

f5: 1/(x(x-1))

+

f6: 1/(x(x+1))

+

f7: 1/(x(x+1)(x-1))

+

f5a: 1/x*1/(x-1)

+

f6a: 1/x*1/(x+1)

+

f7a: 1/x*1/(x+1)*1/(x-1)

+ +

+

+

+

+

+

+

+

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+

+

+ + +

+

+

+

+ +

+

+

+

+ +

+

+

+

+

+

+ + `, + }); + + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/f10n"].stateValues.text).eq("∞"); + expect(stateVariables["/f10s"].stateValues.text).eq("∞"); + expect(stateVariables["/f20n"].stateValues.text).eq("-∞"); + expect(stateVariables["/f20s"].stateValues.text).eq("-∞"); + expect(stateVariables["/f30n"].stateValues.text).eq("-∞"); + expect(stateVariables["/f30s"].stateValues.text).eq("-∞"); + expect(stateVariables["/f40n"].stateValues.text).eq("∞"); + expect(stateVariables["/f40s"].stateValues.text).eq("∞"); + expect(stateVariables["/f50n"].stateValues.text).eq("-∞"); + expect(stateVariables["/f50s"].stateValues.text).eq("-∞"); + expect(stateVariables["/f51n"].stateValues.text).eq("∞"); + expect(stateVariables["/f51s"].stateValues.text).eq("∞"); + expect(stateVariables["/f60n"].stateValues.text).eq("∞"); + expect(stateVariables["/f60s"].stateValues.text).eq("∞"); + expect(stateVariables["/f6n1n"].stateValues.text).eq("-∞"); + expect(stateVariables["/f6n1s"].stateValues.text).eq("-∞"); + expect(stateVariables["/f70n"].stateValues.text).eq("-∞"); + expect(stateVariables["/f70s"].stateValues.text).eq("-∞"); + expect(stateVariables["/f71n"].stateValues.text).eq("∞"); + expect(stateVariables["/f71s"].stateValues.text).eq("∞"); + expect(stateVariables["/f7n1n"].stateValues.text).eq("∞"); + expect(stateVariables["/f7n1s"].stateValues.text).eq("∞"); + expect(stateVariables["/f5a0n"].stateValues.text).eq("-∞"); + expect(stateVariables["/f5a0s"].stateValues.text).eq("-∞"); + expect(stateVariables["/f5a1n"].stateValues.text).eq("∞"); + expect(stateVariables["/f5a1s"].stateValues.text).eq("∞"); + expect(stateVariables["/f6a0n"].stateValues.text).eq("∞"); + expect(stateVariables["/f6a0s"].stateValues.text).eq("∞"); + expect(stateVariables["/f6an1n"].stateValues.text).eq("-∞"); + expect(stateVariables["/f6an1s"].stateValues.text).eq("-∞"); + expect(stateVariables["/f7a0n"].stateValues.text).eq("-∞"); + expect(stateVariables["/f7a0s"].stateValues.text).eq("-∞"); + expect(stateVariables["/f7a1n"].stateValues.text).eq("∞"); + expect(stateVariables["/f7a1s"].stateValues.text).eq("∞"); + expect(stateVariables["/f7an1n"].stateValues.text).eq("∞"); + expect(stateVariables["/f7an1s"].stateValues.text).eq("∞"); + }); + + it("evaluate at infinity", async () => { + let core = await createTestCore({ + doenetML: ` +

f1: 1/x

+

f2: 1/(-x)

+

f3: x^3

+

f4: (-x)^3

+

f5: sin(x)

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ + `, + }); + + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/f1pn"].stateValues.text).eq("0"); + expect(stateVariables["/f1ps"].stateValues.text).eq("0"); + expect(stateVariables["/f1mn"].stateValues.text).eq("0"); + expect(stateVariables["/f1ms"].stateValues.text).eq("0"); + expect(stateVariables["/f2pn"].stateValues.text).eq("0"); + expect(stateVariables["/f2ps"].stateValues.text).eq("0"); + expect(stateVariables["/f2mn"].stateValues.text).eq("0"); + expect(stateVariables["/f2ms"].stateValues.text).eq("0"); + expect(stateVariables["/f3pn"].stateValues.text).eq("∞"); + expect(stateVariables["/f3ps"].stateValues.text).eq("∞"); + expect(stateVariables["/f3mn"].stateValues.text).eq("-∞"); + expect(stateVariables["/f3ms"].stateValues.text).eq("-∞"); + expect(stateVariables["/f4pn"].stateValues.text).eq("-∞"); + expect(stateVariables["/f4ps"].stateValues.text).eq("-∞"); + expect(stateVariables["/f4mn"].stateValues.text).eq("∞"); + expect(stateVariables["/f4ms"].stateValues.text).eq("∞"); + expect(stateVariables["/f5pn"].stateValues.text).eq("NaN"); + expect(stateVariables["/f5ps"].stateValues.text).eq("sin(∞)"); + expect(stateVariables["/f5mn"].stateValues.text).eq("NaN"); + expect(stateVariables["/f5ms"].stateValues.text).eq("sin(-∞)"); + }); + + it("evaluate at infinity, interpolated functions", async () => { + let core = await createTestCore({ + doenetML: ` +

f1:

+

f2:

+

f3:

+

f4:

+

f5:

+ +

+

+ +

+

+ +

+

+ +

+

+ +

+

+ + `, + }); + + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/f1pn"].stateValues.text).eq("2"); + expect(stateVariables["/f1mn"].stateValues.text).eq("2"); + expect(stateVariables["/f2pn"].stateValues.text).eq("∞"); + expect(stateVariables["/f2mn"].stateValues.text).eq("-∞"); + expect(stateVariables["/f3pn"].stateValues.text).eq("-∞"); + expect(stateVariables["/f3mn"].stateValues.text).eq("∞"); + expect(stateVariables["/f4pn"].stateValues.text).eq("-∞"); + expect(stateVariables["/f4mn"].stateValues.text).eq("∞"); + expect(stateVariables["/f5pn"].stateValues.text).eq("∞"); + expect(stateVariables["/f5mn"].stateValues.text).eq("-∞"); + }); + + it("evaluate at domain boundary, numeric", async () => { + let core = await createTestCore({ + doenetML: ` +

f1: sin(x)

+

f2: sin(x)

+

f3: sin(x)

+

f4: sin(x)

+ +

+

+

+ +

+

+

+ +

+

+

+ +

+

+

+ + `, + }); + + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/f1l"].stateValues.text).eq("NaN"); + expect(stateVariables["/f1r"].stateValues.text).eq("NaN"); + expect(stateVariables["/f1m"].stateValues.text).eq("0"); + expect(stateVariables["/f2l"].stateValues.text).eq("NaN"); + expect(stateVariables["/f2r"].stateValues.text).eq("0"); + expect(stateVariables["/f2m"].stateValues.text).eq("0"); + expect(stateVariables["/f3l"].stateValues.text).eq("0"); + expect(stateVariables["/f3r"].stateValues.text).eq("0"); + expect(stateVariables["/f3m"].stateValues.text).eq("0"); + expect(stateVariables["/f4l"].stateValues.text).eq("0"); + expect(stateVariables["/f4r"].stateValues.text).eq("NaN"); + expect(stateVariables["/f4m"].stateValues.text).eq("0"); + + // test functions + let f1 = (await core.components!["/f1"].stateValues.fs)[0]; + let f2 = (await core.components!["/f2"].stateValues.fs)[0]; + let f3 = (await core.components!["/f3"].stateValues.fs)[0]; + let f4 = (await core.components!["/f4"].stateValues.fs)[0]; + + expect(f1(-Math.PI)).eqls(NaN); + expect(f1(0)).eqls(0); + expect(f1(Math.PI)).eqls(NaN); + expect(f2(-Math.PI)).eqls(NaN); + expect(f2(0)).eqls(0); + expect(f2(Math.PI)).closeTo(0, 1e-14); + expect(f3(-Math.PI)).closeTo(0, 1e-14); + expect(f3(0)).eqls(0); + expect(f3(Math.PI)).closeTo(0, 1e-14); + expect(f4(-Math.PI)).closeTo(0, 1e-14); + expect(f4(0)).eqls(0); + expect(f4(Math.PI)).eqls(NaN); + }); + + it("evaluate at domain boundary, symbolic", async () => { + let core = await createTestCore({ + doenetML: ` +

f1: sin(x)

+

f2: sin(x)

+

f3: sin(x)

+

f4: sin(x)

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ + `, + }); + + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/f1l"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/f1r"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/f1m"].stateValues.text).eq("0"); + expect(stateVariables["/f1y"].stateValues.text).eq("sin(10 y)"); + expect(stateVariables["/f2l"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/f2r"].stateValues.text).eq("sin(π)"); // eventually should be '0' once can simplify sin(pi) + expect(stateVariables["/f2m"].stateValues.text).eq("0"); + expect(stateVariables["/f2y"].stateValues.text).eq("sin(10 y)"); + expect(stateVariables["/f3l"].stateValues.text).eq("sin(-π)"); // eventually should be '0' once can simplify sin(-pi) + expect(stateVariables["/f3r"].stateValues.text).eq("sin(π)"); // eventually should be '0' once can simplify sin(pi) + expect(stateVariables["/f3m"].stateValues.text).eq("0"); + expect(stateVariables["/f3y"].stateValues.text).eq("sin(10 y)"); + expect(stateVariables["/f4l"].stateValues.text).eq("sin(-π)"); // eventually should be '0' once can simplify sin(-pi) + expect(stateVariables["/f4r"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/f4m"].stateValues.text).eq("0"); + expect(stateVariables["/f4y"].stateValues.text).eq("sin(10 y)"); + }); + + it("evaluate at domain boundary, numeric, multidimensional", async () => { + let core = await createTestCore({ + doenetML: ` +

f1: sin(x+y)

+

f2: sin(x+y)

+

f3: sin(x+y)

+

f4: sin(x+y)

+ +

+

+

+

+

+

+

+

+

+ +

+

+

+

+

+

+

+

+

+ +

+

+

+

+

+

+

+

+

+ +

+

+

+

+

+

+

+

+

+ + + `, + }); + + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/f1ll"].stateValues.text).eq("NaN"); + expect(stateVariables["/f1lr"].stateValues.text).eq("NaN"); + expect(stateVariables["/f1lm"].stateValues.text).eq("NaN"); + expect(stateVariables["/f1rl"].stateValues.text).eq("NaN"); + expect(stateVariables["/f1rr"].stateValues.text).eq("NaN"); + expect(stateVariables["/f1rm"].stateValues.text).eq("NaN"); + expect(stateVariables["/f1ml"].stateValues.text).eq("NaN"); + expect(stateVariables["/f1mr"].stateValues.text).eq("NaN"); + expect(stateVariables["/f1mm"].stateValues.text).eq("0"); + expect(stateVariables["/f2ll"].stateValues.text).eq("NaN"); + expect(stateVariables["/f2lr"].stateValues.text).eq("NaN"); + expect(stateVariables["/f2lm"].stateValues.text).eq("NaN"); + expect(stateVariables["/f2rl"].stateValues.text).eq("NaN"); + expect(stateVariables["/f2rr"].stateValues.text).eq("0"); + expect(stateVariables["/f2rm"].stateValues.text).eq("0"); + expect(stateVariables["/f2ml"].stateValues.text).eq("NaN"); + expect(stateVariables["/f2mr"].stateValues.text).eq("0"); + expect(stateVariables["/f2mm"].stateValues.text).eq("0"); + expect(stateVariables["/f3ll"].stateValues.text).eq("0"); + expect(stateVariables["/f3lr"].stateValues.text).eq("0"); + expect(stateVariables["/f3lm"].stateValues.text).eq("0"); + expect(stateVariables["/f3rl"].stateValues.text).eq("0"); + expect(stateVariables["/f3rr"].stateValues.text).eq("0"); + expect(stateVariables["/f3rm"].stateValues.text).eq("0"); + expect(stateVariables["/f3ml"].stateValues.text).eq("0"); + expect(stateVariables["/f3mr"].stateValues.text).eq("0"); + expect(stateVariables["/f3mm"].stateValues.text).eq("0"); + expect(stateVariables["/f4ll"].stateValues.text).eq("0"); + expect(stateVariables["/f4lr"].stateValues.text).eq("NaN"); + expect(stateVariables["/f4lm"].stateValues.text).eq("0"); + expect(stateVariables["/f4rl"].stateValues.text).eq("NaN"); + expect(stateVariables["/f4rr"].stateValues.text).eq("NaN"); + expect(stateVariables["/f4rm"].stateValues.text).eq("NaN"); + expect(stateVariables["/f4ml"].stateValues.text).eq("0"); + expect(stateVariables["/f4mr"].stateValues.text).eq("NaN"); + expect(stateVariables["/f4mm"].stateValues.text).eq("0"); + + // test functions + let f1 = (await core.components!["/f1"].stateValues.fs)[0]; + let f2 = (await core.components!["/f2"].stateValues.fs)[0]; + let f3 = (await core.components!["/f3"].stateValues.fs)[0]; + let f4 = (await core.components!["/f4"].stateValues.fs)[0]; + + expect(f1(-Math.PI, -Math.PI)).eqls(NaN); + expect(f1(-Math.PI, 0)).eqls(NaN); + expect(f1(-Math.PI, Math.PI)).eqls(NaN); + expect(f1(0, -Math.PI)).eqls(NaN); + expect(f1(0, 0)).eqls(0); + expect(f1(0, Math.PI)).eqls(NaN); + expect(f1(Math.PI, -Math.PI)).eqls(NaN); + expect(f1(Math.PI, 0)).eqls(NaN); + expect(f1(Math.PI, Math.PI)).eqls(NaN); + + expect(f2(-Math.PI, -Math.PI)).eqls(NaN); + expect(f2(-Math.PI, 0)).eqls(NaN); + expect(f2(-Math.PI, Math.PI)).eqls(NaN); + expect(f2(0, -Math.PI)).eqls(NaN); + expect(f2(0, 0)).eqls(0); + expect(f2(0, Math.PI)).closeTo(0, 1e-14); + expect(f2(Math.PI, -Math.PI)).eqls(NaN); + expect(f2(Math.PI, 0)).closeTo(0, 1e-14); + expect(f2(Math.PI, Math.PI)).closeTo(0, 1e-14); + + expect(f3(-Math.PI, -Math.PI)).closeTo(0, 1e-14); + expect(f3(-Math.PI, 0)).closeTo(0, 1e-14); + expect(f3(-Math.PI, Math.PI)).closeTo(0, 1e-14); + expect(f3(0, -Math.PI)).closeTo(0, 1e-14); + expect(f3(0, 0)).eqls(0); + expect(f3(0, Math.PI)).closeTo(0, 1e-14); + expect(f3(Math.PI, -Math.PI)).closeTo(0, 1e-14); + expect(f3(Math.PI, 0)).closeTo(0, 1e-14); + expect(f3(Math.PI, Math.PI)).closeTo(0, 1e-14); + + expect(f4(-Math.PI, -Math.PI)).closeTo(0, 1e-14); + expect(f4(-Math.PI, 0)).closeTo(0, 1e-14); + expect(f4(-Math.PI, Math.PI)).eqls(NaN); + expect(f4(0, -Math.PI)).closeTo(0, 1e-14); + expect(f4(0, 0)).eqls(0); + expect(f4(0, Math.PI)).eqls(NaN); + expect(f4(Math.PI, -Math.PI)).eqls(NaN); + expect(f4(Math.PI, 0)).eqls(NaN); + expect(f4(Math.PI, Math.PI)).eqls(NaN); + }); + + it("evaluate at domain boundary, symbolic, multidimensional", async () => { + let core = await createTestCore({ + doenetML: ` +

f1: sin(x+y)

+

f2: sin(x+y)

+

f3: sin(x+y)

+

f4: sin(x+y)

+ +

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+ +

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+ +

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+ +

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+ + + `, + }); + + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/f1ll"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/f1lr"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/f1lm"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/f1ly"].stateValues.text).eq("sin(-π + 10 y)"); + expect(stateVariables["/f1rl"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/f1rr"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/f1rm"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/f1ry"].stateValues.text).eq("sin(π + 10 y)"); + expect(stateVariables["/f1ml"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/f1mr"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/f1mm"].stateValues.text).eq("0"); + expect(stateVariables["/f1my"].stateValues.text).eq("sin(10 y)"); + expect(stateVariables["/f1yl"].stateValues.text).eq("sin(-π + 10 y)"); + expect(stateVariables["/f1yr"].stateValues.text).eq("sin(π + 10 y)"); + expect(stateVariables["/f1ym"].stateValues.text).eq("sin(10 y)"); + expect(stateVariables["/f1yy"].stateValues.text).eq("sin(20 y)"); + expect(stateVariables["/f2ll"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/f2lr"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/f2lm"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/f2ly"].stateValues.text).eq("sin(-π + 10 y)"); + expect(stateVariables["/f2rl"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/f2rr"].stateValues.text).eq("sin(2 π)"); + expect(stateVariables["/f2rm"].stateValues.text).eq("sin(π)"); + expect(stateVariables["/f2ry"].stateValues.text).eq("sin(π + 10 y)"); + expect(stateVariables["/f2ml"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/f2mr"].stateValues.text).eq("sin(π)"); + expect(stateVariables["/f2mm"].stateValues.text).eq("0"); + expect(stateVariables["/f2my"].stateValues.text).eq("sin(10 y)"); + expect(stateVariables["/f2yl"].stateValues.text).eq("sin(-π + 10 y)"); + expect(stateVariables["/f2yr"].stateValues.text).eq("sin(π + 10 y)"); + expect(stateVariables["/f2ym"].stateValues.text).eq("sin(10 y)"); + expect(stateVariables["/f2yy"].stateValues.text).eq("sin(20 y)"); + expect(stateVariables["/f3ll"].stateValues.text).eq("sin(-2 π)"); + expect(stateVariables["/f3lr"].stateValues.text).eq("0"); + expect(stateVariables["/f3lm"].stateValues.text).eq("sin(-π)"); + expect(stateVariables["/f3ly"].stateValues.text).eq("sin(-π + 10 y)"); + expect(stateVariables["/f3rl"].stateValues.text).eq("0"); + expect(stateVariables["/f3rr"].stateValues.text).eq("sin(2 π)"); + expect(stateVariables["/f3rm"].stateValues.text).eq("sin(π)"); + expect(stateVariables["/f3ry"].stateValues.text).eq("sin(π + 10 y)"); + expect(stateVariables["/f3ml"].stateValues.text).eq("sin(-π)"); + expect(stateVariables["/f3mr"].stateValues.text).eq("sin(π)"); + expect(stateVariables["/f3mm"].stateValues.text).eq("0"); + expect(stateVariables["/f3my"].stateValues.text).eq("sin(10 y)"); + expect(stateVariables["/f3yl"].stateValues.text).eq("sin(-π + 10 y)"); + expect(stateVariables["/f3yr"].stateValues.text).eq("sin(π + 10 y)"); + expect(stateVariables["/f3ym"].stateValues.text).eq("sin(10 y)"); + expect(stateVariables["/f3yy"].stateValues.text).eq("sin(20 y)"); + expect(stateVariables["/f4ll"].stateValues.text).eq("sin(-2 π)"); + expect(stateVariables["/f4lr"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/f4lm"].stateValues.text).eq("sin(-π)"); + expect(stateVariables["/f4ly"].stateValues.text).eq("sin(-π + 10 y)"); + expect(stateVariables["/f4rl"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/f4rr"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/f4rm"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/f4ry"].stateValues.text).eq("sin(π + 10 y)"); + expect(stateVariables["/f4ml"].stateValues.text).eq("sin(-π)"); + expect(stateVariables["/f4mr"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/f4mm"].stateValues.text).eq("0"); + expect(stateVariables["/f4my"].stateValues.text).eq("sin(10 y)"); + expect(stateVariables["/f4yl"].stateValues.text).eq("sin(-π + 10 y)"); + expect(stateVariables["/f4yr"].stateValues.text).eq("sin(π + 10 y)"); + expect(stateVariables["/f4ym"].stateValues.text).eq("sin(10 y)"); + expect(stateVariables["/f4yy"].stateValues.text).eq("sin(20 y)"); + }); + + it("evaluate interpolated at domain boundary", async () => { + let core = await createTestCore({ + doenetML: ` +

f1:

+

f2:

+

f3:

+

f4:

+ +

+

+

+ +

+

+

+ +

+

+

+ +

+

+

+ + `, + }); + + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/f1l"].stateValues.text).eq("NaN"); + expect(stateVariables["/f1r"].stateValues.text).eq("NaN"); + expect(stateVariables["/f1m"].stateValues.text).eq("5"); + expect(stateVariables["/f2l"].stateValues.text).eq("NaN"); + expect(stateVariables["/f2r"].stateValues.text).eq("-1"); + expect(stateVariables["/f2m"].stateValues.text).eq("5"); + expect(stateVariables["/f3l"].stateValues.text).eq("1"); + expect(stateVariables["/f3r"].stateValues.text).eq("-1"); + expect(stateVariables["/f3m"].stateValues.text).eq("5"); + expect(stateVariables["/f4l"].stateValues.text).eq("1"); + expect(stateVariables["/f4r"].stateValues.text).eq("NaN"); + expect(stateVariables["/f4m"].stateValues.text).eq("5"); + }); + + it("evaluate functions based on functions, symbolic", async () => { + let core = await createTestCore({ + doenetML: ` +

f: x^2

+

fa: $$f(x)

+

fxp1: $$f(x+1)

+

fp1: $$f(x)+1

+

fp1a: $$f(x)+1

+

fxp1p1: $$f(x+1)+1

+

fm: $$f(x)

+

fp1m: $$f(x)+1

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ + + `, + }); + + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/f0"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/f1"].stateValues.text).eq("1"); + expect(stateVariables["/f2"].stateValues.text).eq("4"); + expect(stateVariables["/f3"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/fa0"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/fa1"].stateValues.text).eq("1"); + expect(stateVariables["/fa2"].stateValues.text).eq("4"); + expect(stateVariables["/fa3"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/fxp10"].stateValues.text).eq("1"); + expect(stateVariables["/fxp11"].stateValues.text).eq("4"); + expect(stateVariables["/fxp12"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/fxp13"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/fp10"].stateValues.text).eq("\uff3f + 1"); + expect(stateVariables["/fp11"].stateValues.text).eq("2"); + expect(stateVariables["/fp12"].stateValues.text).eq("5"); + expect(stateVariables["/fp13"].stateValues.text).eq("\uff3f + 1"); + expect(stateVariables["/fp1a0"].stateValues.text).eq("\uff3f + 1"); + expect(stateVariables["/fp1a1"].stateValues.text).eq("2"); + expect(stateVariables["/fp1a2"].stateValues.text).eq("5"); + expect(stateVariables["/fp1a3"].stateValues.text).eq("\uff3f + 1"); + expect(stateVariables["/fxp1p10"].stateValues.text).eq("2"); + expect(stateVariables["/fxp1p11"].stateValues.text).eq("5"); + expect(stateVariables["/fxp1p12"].stateValues.text).eq("\uff3f + 1"); + expect(stateVariables["/fxp1p13"].stateValues.text).eq("\uff3f + 1"); + expect(stateVariables["/fm0"].stateValues.text).eq("0"); + expect(stateVariables["/fm1"].stateValues.text).eq("1"); + expect(stateVariables["/fm2"].stateValues.text).eq("4"); + expect(stateVariables["/fm3"].stateValues.text).eq("9"); + expect(stateVariables["/fp1m0"].stateValues.text).eq("1"); + expect(stateVariables["/fp1m1"].stateValues.text).eq("2"); + expect(stateVariables["/fp1m2"].stateValues.text).eq("5"); + expect(stateVariables["/fp1m3"].stateValues.text).eq("10"); + }); + + it("evaluate functions based on functions, numeric", async () => { + let core = await createTestCore({ + doenetML: ` +

f: x^2

+

fa: $$f(x)

+

fxp1: $$f(x+1)

+

fp1: $$f(x)+1

+

fp1a: $$f(x)+1

+

fxp1p1: $$f(x+1)+1

+

fm: $$f(x)

+

fp1m: $$f(x)+1

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ + + `, + }); + + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/f0"].stateValues.text).eq("NaN"); + expect(stateVariables["/f1"].stateValues.text).eq("1"); + expect(stateVariables["/f2"].stateValues.text).eq("4"); + expect(stateVariables["/f3"].stateValues.text).eq("NaN"); + expect(stateVariables["/fa0"].stateValues.text).eq("NaN"); + expect(stateVariables["/fa1"].stateValues.text).eq("1"); + expect(stateVariables["/fa2"].stateValues.text).eq("4"); + expect(stateVariables["/fa3"].stateValues.text).eq("NaN"); + expect(stateVariables["/fxp10"].stateValues.text).eq("1"); + expect(stateVariables["/fxp11"].stateValues.text).eq("4"); + expect(stateVariables["/fxp12"].stateValues.text).eq("NaN"); + expect(stateVariables["/fxp13"].stateValues.text).eq("NaN"); + expect(stateVariables["/fp10"].stateValues.text).eq("NaN"); + expect(stateVariables["/fp11"].stateValues.text).eq("2"); + expect(stateVariables["/fp12"].stateValues.text).eq("5"); + expect(stateVariables["/fp13"].stateValues.text).eq("NaN"); + expect(stateVariables["/fp1a0"].stateValues.text).eq("NaN"); + expect(stateVariables["/fp1a1"].stateValues.text).eq("2"); + expect(stateVariables["/fp1a2"].stateValues.text).eq("5"); + expect(stateVariables["/fp1a3"].stateValues.text).eq("NaN"); + expect(stateVariables["/fxp1p10"].stateValues.text).eq("2"); + expect(stateVariables["/fxp1p11"].stateValues.text).eq("5"); + expect(stateVariables["/fxp1p12"].stateValues.text).eq("NaN"); + expect(stateVariables["/fxp1p13"].stateValues.text).eq("NaN"); + expect(stateVariables["/fm0"].stateValues.text).eq("NaN"); + expect(stateVariables["/fm1"].stateValues.text).eq("NaN"); + expect(stateVariables["/fm2"].stateValues.text).eq("NaN"); + expect(stateVariables["/fm3"].stateValues.text).eq("NaN"); + expect(stateVariables["/fp1m0"].stateValues.text).eq("NaN"); + expect(stateVariables["/fp1m1"].stateValues.text).eq("NaN"); + expect(stateVariables["/fp1m2"].stateValues.text).eq("NaN"); + expect(stateVariables["/fp1m3"].stateValues.text).eq("NaN"); + + // test functions + let f = stateVariables["/f"].stateValues.fs[0]; + let fa = stateVariables["/fa"].stateValues.fs[0]; + let fxp1 = stateVariables["/fxp1"].stateValues.fs[0]; + let fp1 = stateVariables["/fp1"].stateValues.fs[0]; + let fp1a = stateVariables["/fp1a"].stateValues.fs[0]; + let fxp1p1 = stateVariables["/fxp1p1"].stateValues.fs[0]; + let fm = stateVariables["/fm"].stateValues.fs[0]; + let fp1m = stateVariables["/fp1m"].stateValues.fs[0]; + + expect(f(0)).eqls(NaN); + expect(f(1)).eqls(1); + expect(f(2)).eqls(4); + expect(f(3)).eqls(NaN); + + expect(fa(0)).eqls(NaN); + expect(fa(1)).eqls(1); + expect(fa(2)).eqls(4); + expect(fa(3)).eqls(NaN); + + expect(fxp1(0)).eqls(1); + expect(fxp1(1)).eqls(4); + expect(fxp1(2)).eqls(NaN); + expect(fxp1(3)).eqls(NaN); + + expect(fp1(0)).eqls(NaN); + expect(fp1(1)).eqls(2); + expect(fp1(2)).eqls(5); + expect(fp1(3)).eqls(NaN); + + expect(fp1a(0)).eqls(NaN); + expect(fp1a(1)).eqls(2); + expect(fp1a(2)).eqls(5); + expect(fp1a(3)).eqls(NaN); + + expect(fxp1p1(0)).eqls(2); + expect(fxp1p1(1)).eqls(5); + expect(fxp1p1(2)).eqls(NaN); + expect(fxp1p1(3)).eqls(NaN); + + expect(fm(0)).eqls(NaN); + expect(fm(1)).eqls(NaN); + expect(fm(2)).eqls(NaN); + expect(fm(3)).eqls(NaN); + + expect(fp1m(0)).eqls(NaN); + expect(fp1m(1)).eqls(NaN); + expect(fp1m(2)).eqls(NaN); + expect(fp1m(3)).eqls(NaN); + }); + + it("evaluate functions based on functions, numeric then symbolic", async () => { + let core = await createTestCore({ + doenetML: ` +

f: x^2

+

fa: $$f(x)

+

fxp1: $$f(x+1)

+

fpy: $$f(x)+y

+

fpya: $$f(x)+y

+

fxp1py: $$f(x+1)+y

+

fm: $$f(x)

+

fpym: $$f(x)+y

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ + + `, + }); + + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/f0"].stateValues.text).eq("NaN"); + expect(stateVariables["/f1"].stateValues.text).eq("1"); + expect(stateVariables["/f2"].stateValues.text).eq("4"); + expect(stateVariables["/f3"].stateValues.text).eq("NaN"); + expect(stateVariables["/fa0"].stateValues.text).eq("NaN"); + expect(stateVariables["/fa1"].stateValues.text).eq("1"); + expect(stateVariables["/fa2"].stateValues.text).eq("4"); + expect(stateVariables["/fa3"].stateValues.text).eq("NaN"); + expect(stateVariables["/fxp10"].stateValues.text).eq("1"); + expect(stateVariables["/fxp11"].stateValues.text).eq("4"); + expect(stateVariables["/fxp12"].stateValues.text).eq("NaN"); + expect(stateVariables["/fxp13"].stateValues.text).eq("NaN"); + expect(stateVariables["/fpy0"].stateValues.text).eq("y + NaN"); + expect(stateVariables["/fpy1"].stateValues.text).eq("y + 1"); + expect(stateVariables["/fpy2"].stateValues.text).eq("y + 4"); + expect(stateVariables["/fpy3"].stateValues.text).eq("y + NaN"); + expect(stateVariables["/fpya0"].stateValues.text).eq("y + NaN"); + expect(stateVariables["/fpya1"].stateValues.text).eq("y + 1"); + expect(stateVariables["/fpya2"].stateValues.text).eq("y + 4"); + expect(stateVariables["/fpya3"].stateValues.text).eq("y + NaN"); + expect(stateVariables["/fxp1py0"].stateValues.text).eq("y + 1"); + expect(stateVariables["/fxp1py1"].stateValues.text).eq("y + 4"); + expect(stateVariables["/fxp1py2"].stateValues.text).eq("y + NaN"); + expect(stateVariables["/fxp1py3"].stateValues.text).eq("y + NaN"); + expect(stateVariables["/fm0"].stateValues.text).eq("NaN"); + expect(stateVariables["/fm1"].stateValues.text).eq("NaN"); + expect(stateVariables["/fm2"].stateValues.text).eq("NaN"); + expect(stateVariables["/fm3"].stateValues.text).eq("NaN"); + expect(stateVariables["/fpym0"].stateValues.text).eq("y + NaN"); + expect(stateVariables["/fpym1"].stateValues.text).eq("y + NaN"); + expect(stateVariables["/fpym2"].stateValues.text).eq("y + NaN"); + expect(stateVariables["/fpym3"].stateValues.text).eq("y + NaN"); + }); + + it("evaluate functions based on functions, symbolic then numeric", async () => { + let core = await createTestCore({ + doenetML: ` +

f: x^2

+

fa: $$f(x)

+

fxp1: $$f(x+1)

+

fp1: $$f(x)+1

+

fp1a: $$f(x)+1

+

fxp1p1: $$f(x+1)+1

+

fm: $$f(x)

+

fp1m: $$f(x)+1

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ + + `, + }); + + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/f0"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/f1"].stateValues.text).eq("1"); + expect(stateVariables["/f2"].stateValues.text).eq("4"); + expect(stateVariables["/f3"].stateValues.text).eq("\uff3f"); + expect(stateVariables["/fa0"].stateValues.text).eq("NaN"); + expect(stateVariables["/fa1"].stateValues.text).eq("1"); + expect(stateVariables["/fa2"].stateValues.text).eq("4"); + expect(stateVariables["/fa3"].stateValues.text).eq("NaN"); + expect(stateVariables["/fxp10"].stateValues.text).eq("1"); + expect(stateVariables["/fxp11"].stateValues.text).eq("4"); + expect(stateVariables["/fxp12"].stateValues.text).eq("NaN"); + expect(stateVariables["/fxp13"].stateValues.text).eq("NaN"); + expect(stateVariables["/fp10"].stateValues.text).eq("NaN"); + expect(stateVariables["/fp11"].stateValues.text).eq("2"); + expect(stateVariables["/fp12"].stateValues.text).eq("5"); + expect(stateVariables["/fp13"].stateValues.text).eq("NaN"); + expect(stateVariables["/fp1a0"].stateValues.text).eq("NaN"); + expect(stateVariables["/fp1a1"].stateValues.text).eq("2"); + expect(stateVariables["/fp1a2"].stateValues.text).eq("5"); + expect(stateVariables["/fp1a3"].stateValues.text).eq("NaN"); + expect(stateVariables["/fxp1p10"].stateValues.text).eq("2"); + expect(stateVariables["/fxp1p11"].stateValues.text).eq("5"); + expect(stateVariables["/fxp1p12"].stateValues.text).eq("NaN"); + expect(stateVariables["/fxp1p13"].stateValues.text).eq("NaN"); + expect(stateVariables["/fm0"].stateValues.text).eq("0"); + expect(stateVariables["/fm1"].stateValues.text).eq("1"); + expect(stateVariables["/fm2"].stateValues.text).eq("4"); + expect(stateVariables["/fm3"].stateValues.text).eq("9"); + expect(stateVariables["/fp1m0"].stateValues.text).eq("1"); + expect(stateVariables["/fp1m1"].stateValues.text).eq("2"); + expect(stateVariables["/fp1m2"].stateValues.text).eq("5"); + expect(stateVariables["/fp1m3"].stateValues.text).eq("10"); + + // test functions + let f = stateVariables["/f"].stateValues.fs[0]; + let fa = stateVariables["/fa"].stateValues.fs[0]; + let fxp1 = stateVariables["/fxp1"].stateValues.fs[0]; + let fp1 = stateVariables["/fp1"].stateValues.fs[0]; + let fp1a = stateVariables["/fp1a"].stateValues.fs[0]; + let fxp1p1 = stateVariables["/fxp1p1"].stateValues.fs[0]; + let fm = stateVariables["/fm"].stateValues.fs[0]; + let fp1m = stateVariables["/fp1m"].stateValues.fs[0]; + + // Note: function from definition is numeric for all but f itself + expect(f(me.fromAst(0)).tree).eqls("\uff3f"); + expect(f(me.fromAst(1)).tree).eqls(1); + expect(f(me.fromAst(2)).tree).eqls(4); + expect(f(me.fromAst(3)).tree).eqls("\uff3f"); + + expect(fa(0)).eqls(NaN); + expect(fa(1)).eqls(1); + expect(fa(2)).eqls(4); + expect(fa(3)).eqls(NaN); + + expect(fxp1(0)).eqls(1); + expect(fxp1(1)).eqls(4); + expect(fxp1(2)).eqls(NaN); + expect(fxp1(3)).eqls(NaN); + + expect(fp1(0)).eqls(NaN); + expect(fp1(1)).eqls(2); + expect(fp1(2)).eqls(5); + expect(fp1(3)).eqls(NaN); + + expect(fp1a(0)).eqls(NaN); + expect(fp1a(1)).eqls(2); + expect(fp1a(2)).eqls(5); + expect(fp1a(3)).eqls(NaN); + + expect(fxp1p1(0)).eqls(2); + expect(fxp1p1(1)).eqls(5); + expect(fxp1p1(2)).eqls(NaN); + expect(fxp1p1(3)).eqls(NaN); + + expect(fm(0)).eqls(0); + expect(fm(1)).eqls(1); + expect(fm(2)).eqls(4); + expect(fm(3)).eqls(9); + + expect(fp1m(0)).eqls(1); + expect(fp1m(1)).eqls(2); + expect(fp1m(2)).eqls(5); + expect(fp1m(3)).eqls(10); + }); + + it("an evaluate copied into a function can be reevaluated", async () => { + let core = await createTestCore({ + doenetML: ` + 2x + + $$f(x) + $fx + $$f(x)+1 + $fx+1 +

$$g(2)

+

$$ga(2)

+

$$h(2)

+

$$ha(2)

+ `, + }); + + const stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/f"].stateValues.latex)).eq("2x"); + expect(cleanLatex(stateVariables["/fx"].stateValues.latex)).eq("NaN"); + expect(cleanLatex(stateVariables["/g"].stateValues.latex)).eq("\uff3f"); + expect(cleanLatex(stateVariables["/ga"].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables["/h"].stateValues.latex)).eq("\uff3f"); + expect(cleanLatex(stateVariables["/ha"].stateValues.latex)).eq( + "\uff3f", + ); + expect(stateVariables["/pg"].stateValues.text).eq("4"); + expect(stateVariables["/pga"].stateValues.text).eq("4"); + expect(stateVariables["/ph"].stateValues.text).eq("5"); + expect(stateVariables["/pha"].stateValues.text).eq("5"); + }); + + it("evaluate functions based on interpolated function", async () => { + let core = await createTestCore({ + doenetML: ` +

f: x^2

+

fa: $$f(x)

+

fxp1: $$f(x+1)

+

fp1: $$f(x)+1

+

fp1a: $$f(x)+1

+

fxp1p1: $$f(x+1)+1

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ +

+

+

+

+ + + `, + }); + + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/f0"].stateValues.text).eq("0"); + expect(stateVariables["/f1"].stateValues.text).eq("3"); + expect(stateVariables["/f2"].stateValues.text).eq("4"); + expect(stateVariables["/f3"].stateValues.text).eq("3"); + expect(stateVariables["/fa0"].stateValues.text).eq("0"); + expect(stateVariables["/fa1"].stateValues.text).eq("3"); + expect(stateVariables["/fa2"].stateValues.text).eq("4"); + expect(stateVariables["/fa3"].stateValues.text).eq("3"); + expect(stateVariables["/fxp10"].stateValues.text).eq("3"); + expect(stateVariables["/fxp11"].stateValues.text).eq("4"); + expect(stateVariables["/fxp12"].stateValues.text).eq("3"); + expect(stateVariables["/fxp13"].stateValues.text).eq("0"); + expect(stateVariables["/fp10"].stateValues.text).eq("1"); + expect(stateVariables["/fp11"].stateValues.text).eq("4"); + expect(stateVariables["/fp12"].stateValues.text).eq("5"); + expect(stateVariables["/fp13"].stateValues.text).eq("4"); + expect(stateVariables["/fp1a0"].stateValues.text).eq("1"); + expect(stateVariables["/fp1a1"].stateValues.text).eq("4"); + expect(stateVariables["/fp1a2"].stateValues.text).eq("5"); + expect(stateVariables["/fp1a3"].stateValues.text).eq("4"); + expect(stateVariables["/fxp1p10"].stateValues.text).eq("4"); + expect(stateVariables["/fxp1p11"].stateValues.text).eq("5"); + expect(stateVariables["/fxp1p12"].stateValues.text).eq("4"); + expect(stateVariables["/fxp1p13"].stateValues.text).eq("1"); + + // test functions + let f = stateVariables["/f"].stateValues.fs[0]; + let fa = stateVariables["/fa"].stateValues.fs[0]; + let fxp1 = stateVariables["/fxp1"].stateValues.fs[0]; + let fp1 = stateVariables["/fp1"].stateValues.fs[0]; + let fp1a = stateVariables["/fp1a"].stateValues.fs[0]; + let fxp1p1 = stateVariables["/fxp1p1"].stateValues.fs[0]; + + expect(f(me.fromAst(3)).tree).eqls(0); + expect(f(me.fromAst(4)).tree).eqls(3); + expect(f(me.fromAst(5)).tree).eqls(4); + expect(f(me.fromAst(6)).tree).eqls(3); + + expect(fa(me.fromAst(3)).tree).eqls(0); + expect(fa(me.fromAst(4)).tree).eqls(3); + expect(fa(me.fromAst(5)).tree).eqls(4); + expect(fa(me.fromAst(6)).tree).eqls(3); + + expect(fxp1(me.fromAst(3)).tree).eqls(3); + expect(fxp1(me.fromAst(4)).tree).eqls(4); + expect(fxp1(me.fromAst(5)).tree).eqls(3); + expect(fxp1(me.fromAst(6)).tree).eqls(0); + + expect(fp1(me.fromAst(3)).tree).eqls(1); + expect(fp1(me.fromAst(4)).tree).eqls(4); + expect(fp1(me.fromAst(5)).tree).eqls(5); + expect(fp1(me.fromAst(6)).tree).eqls(4); + + expect(fp1a(me.fromAst(3)).tree).eqls(1); + expect(fp1a(me.fromAst(4)).tree).eqls(4); + expect(fp1a(me.fromAst(5)).tree).eqls(5); + expect(fp1a(me.fromAst(6)).tree).eqls(4); + + expect(fxp1p1(me.fromAst(3)).tree).eqls(4); + expect(fxp1p1(me.fromAst(4)).tree).eqls(5); + expect(fxp1p1(me.fromAst(5)).tree).eqls(4); + expect(fxp1p1(me.fromAst(6)).tree).eqls(1); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/extract.test.ts b/packages/doenetml-worker/src/test/tagSpecific/extract.test.ts new file mode 100644 index 000000000..5923bfb09 --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/extract.test.ts @@ -0,0 +1,819 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { + updateBooleanInputValue, + updateMathInputValue, +} from "../utils/actions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +describe("Extract tag tests", async () => { + it("extract copies properties", async () => { + let core = await createTestCore({ + doenetML: ` + x + x + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_math1"].stateValues.modifyIndirectly).eq( + false, + ); + expect(stateVariables["/_math2"].stateValues.modifyIndirectly).eq(true); + expect(stateVariables["/e1"].stateValues.modifyIndirectly).eq(false); + expect(stateVariables["/e2"].stateValues.modifyIndirectly).eq(true); + }); + + it("extract can overwrite base component properties", async () => { + let core = await createTestCore({ + doenetML: ` + x + x + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_math1"].stateValues.modifyIndirectly).eq( + false, + ); + expect(stateVariables["/_math2"].stateValues.modifyIndirectly).eq(true); + expect(stateVariables["/e1"].stateValues.modifyIndirectly).eq(true); + expect(stateVariables["/e2"].stateValues.modifyIndirectly).eq(false); + }); + + it("extract multiple tags", async () => { + let core = await createTestCore({ + doenetML: ` + + (1,2) + (3,4) + (5,6) + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/e1"].stateValues.value.tree).eq(2); + expect(stateVariables["/e2"].stateValues.value.tree).eq(4); + expect(stateVariables["/e3"].stateValues.value.tree).eq(6); + }); + + it("extract still updatable", async () => { + let core = await createTestCore({ + doenetML: ` + + $original{name="copy"} + + ($copy2.y, + $copy{name="copy2"}) + + + + + (1,2) + + `, + }); + + // initial position + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/original"].stateValues.xs[0].tree).eq(1); + expect(stateVariables["/original"].stateValues.xs[1].tree).eq(2); + expect(stateVariables["/copy"].stateValues.xs[0].tree).eq(1); + expect(stateVariables["/copy"].stateValues.xs[1].tree).eq(2); + expect(stateVariables["/transformed"].stateValues.xs[0].tree).eq(2); + expect(stateVariables["/transformed"].stateValues.xs[1].tree).eq(1); + + // move original point + await core.requestAction({ + actionName: "movePoint", + componentName: "/original", + args: { x: -3, y: 5 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/original"].stateValues.xs[0].tree).eq(-3); + expect(stateVariables["/original"].stateValues.xs[1].tree).eq(5); + expect(stateVariables["/copy"].stateValues.xs[0].tree).eq(-3); + expect(stateVariables["/copy"].stateValues.xs[1].tree).eq(5); + expect(stateVariables["/transformed"].stateValues.xs[0].tree).eq(5); + expect(stateVariables["/transformed"].stateValues.xs[1].tree).eq(-3); + + // move copy point + await core.requestAction({ + actionName: "movePoint", + componentName: "/copy", + args: { x: 6, y: -9 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/original"].stateValues.xs[0].tree).eq(6); + expect(stateVariables["/original"].stateValues.xs[1].tree).eq(-9); + expect(stateVariables["/copy"].stateValues.xs[0].tree).eq(6); + expect(stateVariables["/copy"].stateValues.xs[1].tree).eq(-9); + expect(stateVariables["/transformed"].stateValues.xs[0].tree).eq(-9); + expect(stateVariables["/transformed"].stateValues.xs[1].tree).eq(6); + + // move transformed point + await core.requestAction({ + actionName: "movePoint", + componentName: "/transformed", + args: { x: -1, y: -7 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/original"].stateValues.xs[0].tree).eq(-7); + expect(stateVariables["/original"].stateValues.xs[1].tree).eq(-1); + expect(stateVariables["/copy"].stateValues.xs[0].tree).eq(-7); + expect(stateVariables["/copy"].stateValues.xs[1].tree).eq(-1); + expect(stateVariables["/transformed"].stateValues.xs[0].tree).eq(-1); + expect(stateVariables["/transformed"].stateValues.xs[1].tree).eq(-7); + }); + + it("copy prop of extract", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + $extract1.x{assignNames="x1"}, + $extract1.y{assignNames="y1"} + + + (1,2) + (5,6) + $extract1{assignNames="copiedextract"} + + + $copiedextract.x{assignNames="x2"}, + $copiedextract.y{assignNames="y2"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/x1"].stateValues.value.tree).eq(3); + expect(stateVariables["/y1"].stateValues.value.tree).eq(4); + expect(stateVariables["/x2"].stateValues.value.tree).eq(3); + expect(stateVariables["/y2"].stateValues.value.tree).eq(4); + + // move extracted center + + await core.requestAction({ + actionName: "movePoint", + componentName: "/copiedextract", + args: { x: -2, y: -5 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/x1"].stateValues.value.tree).closeTo(-2, 1e-12); + expect(stateVariables["/y1"].stateValues.value.tree).closeTo(-5, 1e-12); + expect(stateVariables["/x2"].stateValues.value.tree).closeTo(-2, 1e-12); + expect(stateVariables["/y2"].stateValues.value.tree).closeTo(-5, 1e-12); + expect(stateVariables["/_point1"].stateValues.xs[0].tree).closeTo( + -4, + 1e-12, + ); + expect(stateVariables["/_point1"].stateValues.xs[1].tree).closeTo( + -7, + 1e-12, + ); + expect(stateVariables["/_point2"].stateValues.xs[0].tree).closeTo( + 0, + 1e-12, + ); + expect(stateVariables["/_point2"].stateValues.xs[1].tree).closeTo( + -3, + 1e-12, + ); + + // move points 1 and 2 + + await core.requestAction({ + actionName: "movePoint", + componentName: "/_point1", + args: { x: 8, y: -1 }, + event: null, + }); + await core.requestAction({ + actionName: "movePoint", + componentName: "/_point2", + args: { x: -6, y: -7 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/x1"].stateValues.value.tree).closeTo(1, 1e-12); + expect(stateVariables["/y1"].stateValues.value.tree).closeTo(-4, 1e-12); + expect(stateVariables["/x2"].stateValues.value.tree).closeTo(1, 1e-12); + expect(stateVariables["/y2"].stateValues.value.tree).closeTo(-4, 1e-12); + }); + + it("extract from sequence", async () => { + let core = await createTestCore({ + doenetML: ` + + +

+ +

+ +

$extract1

+ + `, + }); + + async function check_items(vals) { + const stateVariables = await returnAllStateVariables(core); + let componentTypes = Array(vals.length).fill("text"); + + expect( + stateVariables["/p1"].activeChildren.map( + (x) => x.componentType, + ), + ).eqls(componentTypes); + expect( + stateVariables["/p2"].activeChildren.map( + (x) => x.componentType, + ), + ).eqls(componentTypes); + expect( + stateVariables["/p1"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ), + ).eqls(vals); + expect( + stateVariables["/p2"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ), + ).eqls(vals); + } + + await check_items([]); + + // set to 3 + await updateMathInputValue({ latex: "3", componentName: "/n", core }); + await check_items(["1", "2", "3"]); + + // increase to 4 + await updateMathInputValue({ latex: "4", componentName: "/n", core }); + await check_items(["1", "2", "3", "4"]); + + // decrease to 2 + await updateMathInputValue({ latex: "2", componentName: "/n", core }); + await check_items(["1", "2"]); + + // increase to 5 + await updateMathInputValue({ latex: "5", componentName: "/n", core }); + await check_items(["1", "2", "3", "4", "5"]); + }); + + it("extract from map", async () => { + let core = await createTestCore({ + doenetML: ` + + + +

+ + + + + + +

+ +

$extract1

+ + `, + }); + + async function check_items(vals) { + const stateVariables = await returnAllStateVariables(core); + let componentTypes = Array(vals.length).fill("math"); + + expect( + stateVariables["/p1"].activeChildren.map( + (x) => x.componentType, + ), + ).eqls(componentTypes); + expect( + stateVariables["/p2"].activeChildren.map( + (x) => x.componentType, + ), + ).eqls(componentTypes); + expect( + stateVariables["/p1"].activeChildren.map( + (x) => + stateVariables[x.componentName].stateValues.value.tree, + ), + ).eqls(vals); + expect( + stateVariables["/p2"].activeChildren.map( + (x) => + stateVariables[x.componentName].stateValues.value.tree, + ), + ).eqls(vals); + } + + await check_items([]); + + // set n to 3 + await updateMathInputValue({ latex: "3", componentName: "/n", core }); + await check_items([ + ["+", 1, "_"], + ["+", 2, "_"], + ["+", 3, "_"], + ]); + + // set m to 7 + await updateMathInputValue({ latex: "7", componentName: "/m", core }); + await check_items([8, 9, 10]); + + // increase n to 4 + await updateMathInputValue({ latex: "4", componentName: "/n", core }); + await check_items([8, 9, 10, 11]); + + // change m to q + await updateMathInputValue({ latex: "q", componentName: "/m", core }); + await check_items([ + ["+", "q", 1], + ["+", "q", 2], + ["+", "q", 3], + ["+", "q", 4], + ]); + + // decrease n to 2 + await updateMathInputValue({ latex: "2", componentName: "/n", core }); + await check_items([ + ["+", "q", 1], + ["+", "q", 2], + ]); + + // set m to -1 + await updateMathInputValue({ latex: "-1", componentName: "/m", core }); + await check_items([0, 1]); + + // increase n to 5 + await updateMathInputValue({ latex: "5", componentName: "/n", core }); + await check_items([0, 1, 2, 3, 4]); + }); + + // not sure if this is desired, but it is current behavior + it("extract ignores hide", async () => { + let core = await createTestCore({ + doenetML: ` +

See hidden text: secret

+ `, + }); + + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq( + "See hidden text: secret", + ); + }); + + it("extracts hide dynamically", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + +

extract 1: hello

+

extract 2: hello

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/e1"].stateValues.text).eq("extract 1: hello"); + expect(stateVariables["/e2"].stateValues.text).eq("extract 2: "); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/h1", + core, + }); + await updateBooleanInputValue({ + boolean: false, + componentName: "/h2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/e1"].stateValues.text).eq("extract 1: "); + expect(stateVariables["/e2"].stateValues.text).eq("extract 2: hello"); + + await updateBooleanInputValue({ + boolean: false, + componentName: "/h1", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/h2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/e1"].stateValues.text).eq("extract 1: hello"); + expect(stateVariables["/e2"].stateValues.text).eq("extract 2: "); + }); + + it("extract componentIndex", async () => { + let core = await createTestCore({ + doenetML: ` +

n:

+ + + (1,2) + (3,4) + + + + + + + + + `, + }); + + async function check_items({ + x1, + y1, + x2, + y2, + Ax, + }: { + x1: number; + y1: number; + x2: number; + y2: number; + Ax?: number; + }) { + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/A"].stateValues.xs.map((x) => x.tree)).eqls( + [x1, y1], + ); + expect(stateVariables["/B"].stateValues.xs.map((x) => x.tree)).eqls( + [x2, y2], + ); + if (Ax === undefined) { + expect(stateVariables["/Ax"]).eq(undefined); + expect(stateVariables["/al2/Ax"]).eq(undefined); + } else { + expect(stateVariables["/Ax"].stateValues.value.tree).eq(Ax); + expect(stateVariables["/al2/Ax"].stateValues.value.tree).eq(Ax); + } + expect(stateVariables["/Bx"]).eq(undefined); + expect(stateVariables["/al2/Bx"]).eq(undefined); + } + + let x1 = 1, + y1 = 2, + x2 = 3, + y2 = 4; + + await check_items({ x1, x2, y1, y2 }); + + // restrict collection to first component + await updateMathInputValue({ latex: "1", componentName: "/n", core }); + await check_items({ x1, x2, y1, y2, Ax: x1 }); + + // move point + x1 = 9; + y1 = -5; + await core.requestAction({ + actionName: "movePoint", + componentName: "/A", + args: { x: x1, y: y1 }, + event: null, + }); + await check_items({ x1, x2, y1, y2, Ax: x1 }); + + // restrict collection to second component + + await updateMathInputValue({ latex: "2", componentName: "/n", core }); + await check_items({ x1, x2, y1, y2, Ax: x2 }); + + x2 = 0; + y2 = 8; + await core.requestAction({ + actionName: "movePoint", + componentName: "/B", + args: { x: x2, y: y2 }, + event: null, + }); + await check_items({ x1, x2, y1, y2, Ax: x2 }); + }); + + it("copy propIndex and componentIndex", async () => { + let core = await createTestCore({ + doenetML: ` +

m:

+

n:

+ + + (1,2) + (3,4) + + + +

+ +

+ +

+ + `, + }); + + async function check_items({ + x1, + y1, + x2, + y2, + n1, + }: { + x1: number; + y1: number; + x2: number; + y2: number; + n1?: number; + }) { + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/A"].stateValues.xs.map((x) => x.tree)).eqls( + [x1, y1], + ); + expect(stateVariables["/B"].stateValues.xs.map((x) => x.tree)).eqls( + [x2, y2], + ); + if (n1 === undefined) { + expect(stateVariables["/n1"]).eq(undefined); + expect(stateVariables["/al2/n1"]).eq(undefined); + } else { + expect(stateVariables["/n1"].stateValues.value.tree).eq(n1); + expect(stateVariables["/al2/n1"].stateValues.value.tree).eq(n1); + } + expect(stateVariables["/n2"]).eq(undefined); + expect(stateVariables["/n3"]).eq(undefined); + expect(stateVariables["/n4"]).eq(undefined); + expect(stateVariables["/al2/n2"]).eq(undefined); + expect(stateVariables["/al2/n3"]).eq(undefined); + expect(stateVariables["/al2/n4"]).eq(undefined); + } + + let x1 = 1, + y1 = 2, + x2 = 3, + y2 = 4; + + await check_items({ x1, x2, y1, y2 }); + + // set propIndex to 1 + + await updateMathInputValue({ latex: "1", componentName: "/n", core }); + await check_items({ x1, x2, y1, y2 }); + + // move point 1 + x1 = 9; + y1 = -5; + await core.requestAction({ + actionName: "movePoint", + componentName: "/A", + args: { x: x1, y: y1 }, + event: null, + }); + await check_items({ x1, x2, y1, y2 }); + + // set componentIndex to 2 + await updateMathInputValue({ latex: "2", componentName: "/m", core }); + await check_items({ x1, x2, y1, y2, n1: x2 }); + + // move point2 + x2 = 0; + y2 = 8; + await core.requestAction({ + actionName: "movePoint", + componentName: "/B", + args: { x: x2, y: y2 }, + event: null, + }); + await check_items({ x1, x2, y1, y2, n1: x2 }); + + // set propIndex to 2 + await updateMathInputValue({ latex: "2", componentName: "/n", core }); + await check_items({ x1, x2, y1, y2, n1: y2 }); + + // set componentIndex to 1 + await updateMathInputValue({ latex: "1", componentName: "/m", core }); + await check_items({ x1, x2, y1, y2, n1: y1 }); + + // set propIndex to 3 + await updateMathInputValue({ latex: "3", componentName: "/n", core }); + await check_items({ x1, x2, y1, y2 }); + + // set propIndex to 1 + await updateMathInputValue({ latex: "1", componentName: "/n", core }); + await check_items({ x1, x2, y1, y2, n1: x1 }); + + // set componentIndex to 3 + await updateMathInputValue({ latex: "3", componentName: "/m", core }); + await check_items({ x1, x2, y1, y2 }); + + // set componentIndex to 2 + await updateMathInputValue({ latex: "2", componentName: "/m", core }); + await check_items({ x1, x2, y1, y2, n1: x2 }); + + // clear propIndex + await updateMathInputValue({ latex: "", componentName: "/n", core }); + await check_items({ x1, x2, y1, y2 }); + }); + + it("copy multidimensional propIndex", async () => { + let core = await createTestCore({ + doenetML: ` +

m:

+

n:

+ + + + + + +

+ $pg +

+ +

+ + `, + }); + + async function check_items({ + x1, + y1, + x2, + y2, + x3, + y3, + n1, + }: { + x1: number; + y1: number; + x2: number; + y2: number; + x3: number; + y3: number; + n1?: number; + }) { + let stateVariables = await returnAllStateVariables(core); + expect( + stateVariables["/pg"].stateValues.vertices.map((x) => + x.map((y) => y.tree), + ), + ).eqls([ + [x1, y1], + [x2, y2], + [x3, y3], + ]); + if (n1 === undefined) { + expect(stateVariables["/n1"]).eq(undefined); + expect(stateVariables["/p2/n1"]).eq(undefined); + } else { + expect(stateVariables["/n1"].stateValues.value.tree).eq(n1); + expect(stateVariables["/p2/n1"].stateValues.value.tree).eq(n1); + } + expect(stateVariables["/n2"]).eq(undefined); + expect(stateVariables["/p2/n2"]).eq(undefined); + } + + let x1 = 1, + y1 = 2, + x2 = 3, + y2 = 4, + x3 = -5, + y3 = 6; + + await check_items({ x1, y1, x2, y2, x3, y3 }); + + // set second propIndex to 1 + await updateMathInputValue({ latex: "1", componentName: "/n", core }); + await check_items({ x1, y1, x2, y2, x3, y3 }); + + // move first point + x1 = 9; + y1 = -5; + await core.requestAction({ + actionName: "movePolygon", + componentName: "/pg", + args: { + pointCoords: { 0: [x1, y1] }, + }, + event: null, + }); + await check_items({ x1, y1, x2, y2, x3, y3 }); + + // set first propIndex to 2 + await updateMathInputValue({ latex: "2", componentName: "/m", core }); + await check_items({ x1, y1, x2, y2, x3, y3, n1: x2 }); + + // move second point + x2 = 0; + y2 = 8; + await core.requestAction({ + actionName: "movePolygon", + componentName: "/pg", + args: { + pointCoords: { 1: [x2, y2] }, + }, + event: null, + }); + await check_items({ x1, y1, x2, y2, x3, y3, n1: x2 }); + + // set second propIndex to 2 + await updateMathInputValue({ latex: "2", componentName: "/n", core }); + await check_items({ x1, y1, x2, y2, x3, y3, n1: y2 }); + + // set first propIndex to 1 + await updateMathInputValue({ latex: "1", componentName: "/m", core }); + await check_items({ x1, y1, x2, y2, x3, y3, n1: y1 }); + + // set second propIndex to 3 + await updateMathInputValue({ latex: "3", componentName: "/n", core }); + await check_items({ x1, y1, x2, y2, x3, y3 }); + + // set second propIndex to 1 + await updateMathInputValue({ latex: "1", componentName: "/n", core }); + await check_items({ x1, y1, x2, y2, x3, y3, n1: x1 }); + + // set first propindex to 4 + await updateMathInputValue({ latex: "4", componentName: "/m", core }); + await check_items({ x1, y1, x2, y2, x3, y3 }); + + // set first propIndex to 3 + await updateMathInputValue({ latex: "3", componentName: "/m", core }); + await check_items({ x1, y1, x2, y2, x3, y3, n1: x3 }); + + // clear second propIndex + await updateMathInputValue({ latex: "", componentName: "/n", core }); + await check_items({ x1, y1, x2, y2, x3, y3 }); + }); + + it("extract is case insensitive", async () => { + let core = await createTestCore({ + doenetML: ` + x + y + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/e1"].stateValues.value).eq("x"); + expect(stateVariables["/e2"].stateValues.value).eq("y"); + }); + + it("createComponentOfType adapts result", async () => { + let core = await createTestCore({ + doenetML: ` + (1/2,2/3) + (3/4,4/5) + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/e1"].stateValues.value.tree).eqls(["/", 1, 2]); + expect(stateVariables["/e2"].stateValues.value).eq(0.75); + }); + + it("fail gracefully if omit prop", async () => { + let core = await createTestCore({ + doenetML: ` +

Nothing here: x

+ `, + }); + + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p"].stateValues.text).eq("Nothing here: "); + + let errorWarnings = core.errorWarnings; + + expect(errorWarnings.errors.length).eq(0); + expect(errorWarnings.warnings.length).eq(1); + + expect(errorWarnings.warnings[0].message).contain( + "Invalid extract. Must have a prop", + ); + expect(errorWarnings.warnings[0].level).eq(1); + expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(2); + expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(31); + expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(2); + expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(63); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/function.test.ts b/packages/doenetml-worker/src/test/tagSpecific/function.test.ts new file mode 100644 index 000000000..b8a111023 --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/function.test.ts @@ -0,0 +1,5821 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { cleanLatex } from "../utils/math"; +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({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(0)).closeTo(0, 1e-12); + expect(f(1)).closeTo(0, 1e-12); + expect(f(2)).closeTo(0, 1e-12); + expect(f(-1)).closeTo(0, 1e-12); + expect(f(-2)).closeTo(0, 1e-12); + }); + + it("function with single minimum as number", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(0)).closeTo(2, 1e-12); + expect(f(1)).closeTo(2 + 1, 1e-12); + expect(f(2)).closeTo(2 + 4, 1e-12); + expect(f(-1)).closeTo(2 + 1, 1e-12); + expect(f(-2)).closeTo(2 + 4, 1e-12); + }); + + it("function with single minimum as half-empty tuple", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(0)).closeTo(2, 1e-12); + expect(f(1)).closeTo(2 + 1, 1e-12); + expect(f(2)).closeTo(2 + 4, 1e-12); + expect(f(-1)).closeTo(2 + 1, 1e-12); + expect(f(-2)).closeTo(2 + 4, 1e-12); + }); + + it("function with single minimum as half-empty tuple (no space)", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(0)).closeTo(2, 1e-12); + expect(f(1)).closeTo(2 + 1, 1e-12); + expect(f(2)).closeTo(2 + 4, 1e-12); + expect(f(-1)).closeTo(2 + 1, 1e-12); + expect(f(-2)).closeTo(2 + 4, 1e-12); + }); + + it("function with single minimum, change x-scale", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(0)).closeTo(2, 1e-12); + expect(f(3)).closeTo(2 + 1, 1e-12); + expect(f(6)).closeTo(2 + 4, 1e-12); + expect(f(-3)).closeTo(2 + 1, 1e-12); + expect(f(-6)).closeTo(2 + 4, 1e-12); + }); + + it("function with single minimum, change x-scale and y-scale", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(0)).closeTo(2, 1e-12); + expect(f(3)).closeTo(2 + 1 * 5, 1e-12); + expect(f(6)).closeTo(2 + 4 * 5, 1e-12); + expect(f(-3)).closeTo(2 + 1 * 5, 1e-12); + expect(f(-6)).closeTo(2 + 4 * 5, 1e-12); + }); + + it("function with single maximum", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(0)).closeTo(3, 1e-12); + expect(f(1)).closeTo(3 - 1, 1e-12); + expect(f(2)).closeTo(3 - 4, 1e-12); + expect(f(-1)).closeTo(3 - 1, 1e-12); + expect(f(-2)).closeTo(3 - 4, 1e-12); + }); + + it("function with single maximum, change x-scale", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(0)).closeTo(3, 1e-12); + expect(f(3)).closeTo(3 - 1, 1e-12); + expect(f(6)).closeTo(3 - 4, 1e-12); + expect(f(-3)).closeTo(3 - 1, 1e-12); + expect(f(-6)).closeTo(3 - 4, 1e-12); + }); + + it("function with single maximum, change x-scale and y-scale", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(0)).closeTo(3, 1e-12); + expect(f(3)).closeTo(3 - 1 * 5, 1e-12); + expect(f(6)).closeTo(3 - 4 * 5, 1e-12); + expect(f(-3)).closeTo(3 - 1 * 5, 1e-12); + expect(f(-6)).closeTo(3 - 4 * 5, 1e-12); + }); + + it("function with single minimum, specify location as half-empty tuple", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(0)).closeTo(4, 1e-12); + expect(f(1)).closeTo(1, 1e-12); + expect(f(2)).closeTo(0, 1e-12); + expect(f(3)).closeTo(1, 1e-12); + expect(f(4)).closeTo(4, 1e-12); + }); + + it("function with single minimum, specify location as half-empty tuple (no space)", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(0)).closeTo(4, 1e-12); + expect(f(1)).closeTo(1, 1e-12); + expect(f(2)).closeTo(0, 1e-12); + expect(f(3)).closeTo(1, 1e-12); + expect(f(4)).closeTo(4, 1e-12); + }); + + it("function with single minimum, specify location and value as tuple", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(0)).closeTo(4 - 3, 1e-12); + expect(f(1)).closeTo(1 - 3, 1e-12); + expect(f(2)).closeTo(0 - 3, 1e-12); + expect(f(3)).closeTo(1 - 3, 1e-12); + expect(f(4)).closeTo(4 - 3, 1e-12); + }); + + it("function with single minimum, specify location and value as tuple", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(0)).closeTo(4 - 3, 1e-12); + expect(f(1)).closeTo(1 - 3, 1e-12); + expect(f(2)).closeTo(0 - 3, 1e-12); + expect(f(3)).closeTo(1 - 3, 1e-12); + expect(f(4)).closeTo(4 - 3, 1e-12); + }); + + it("function with single extremum, specify location and value as tuple", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(0)).closeTo(-4 - 3, 1e-12); + expect(f(1)).closeTo(-1 - 3, 1e-12); + expect(f(2)).closeTo(0 - 3, 1e-12); + expect(f(3)).closeTo(-1 - 3, 1e-12); + expect(f(4)).closeTo(-4 - 3, 1e-12); + }); + + it("function with min and max", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(0)).closeTo(0, 1e-12); + expect(f(1)).closeTo(1, 1e-12); + expect(f(0.5)).closeTo(0.5, 1e-12); + // like parabola to left of minimum + expect(f(-1)).closeTo(1, 1e-12); + expect(f(-2)).closeTo(4, 1e-12); + expect(f(-3)).closeTo(9, 1e-12); + // like parabola to right of maximum + expect(f(2)).closeTo(0, 1e-12); + expect(f(3)).closeTo(-3, 1e-12); + expect(f(4)).closeTo(-8, 1e-12); + }); + + it("function with min and extremum", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(0)).closeTo(0, 1e-12); + expect(f(1)).closeTo(1, 1e-12); + expect(f(0.5)).closeTo(0.5, 1e-12); + // like parabola to left of minimum + expect(f(-1)).closeTo(1, 1e-12); + expect(f(-2)).closeTo(4, 1e-12); + expect(f(-3)).closeTo(9, 1e-12); + // like parabola to right of maximum + expect(f(2)).closeTo(0, 1e-12); + expect(f(3)).closeTo(-3, 1e-12); + expect(f(4)).closeTo(-8, 1e-12); + }); + + it("function with extremum and max", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(0)).closeTo(0, 1e-12); + expect(f(1)).closeTo(1, 1e-12); + expect(f(0.5)).closeTo(0.5, 1e-12); + // like parabola to left of minimum + expect(f(-1)).closeTo(1, 1e-12); + expect(f(-2)).closeTo(4, 1e-12); + expect(f(-3)).closeTo(9, 1e-12); + // like parabola to right of maximum + expect(f(2)).closeTo(0, 1e-12); + expect(f(3)).closeTo(-3, 1e-12); + expect(f(4)).closeTo(-8, 1e-12); + }); + + it("function two extrema, same height", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(0)).closeTo(0, 1e-12); + expect(f(1)).closeTo(0, 1e-12); + expect(f(0.5)).closeTo(-1, 1e-12); + // like parabola to left of maximum + expect(f(-1)).closeTo(-1, 1e-12); + expect(f(-2)).closeTo(-4, 1e-12); + expect(f(-3)).closeTo(-9, 1e-12); + // like parabola to right of maximum + expect(f(2)).closeTo(-1, 1e-12); + expect(f(3)).closeTo(-4, 1e-12); + expect(f(4)).closeTo(-9, 1e-12); + }); + + it("function two extrema, second higher", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(0)).closeTo(0, 1e-12); + expect(f(1)).closeTo(2, 1e-12); + expect(f(0.5)).closeTo(1, 1e-12); + // like parabola to left of minimum + expect(f(-1)).closeTo(1, 1e-12); + expect(f(-2)).closeTo(4, 1e-12); + expect(f(-3)).closeTo(9, 1e-12); + // like parabola to right of maximum + expect(f(2)).closeTo(1, 1e-12); + expect(f(3)).closeTo(-2, 1e-12); + expect(f(4)).closeTo(-7, 1e-12); + }); + + it("function two extrema, second lower", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(0)).closeTo(0, 1e-12); + expect(f(1)).closeTo(-2, 1e-12); + expect(f(0.5)).closeTo(-1, 1e-12); + // like parabola to left of maximum + expect(f(-1)).closeTo(-1, 1e-12); + expect(f(-2)).closeTo(-4, 1e-12); + expect(f(-3)).closeTo(-9, 1e-12); + // like parabola to right of minimum + expect(f(2)).closeTo(-1, 1e-12); + expect(f(3)).closeTo(2, 1e-12); + expect(f(4)).closeTo(7, 1e-12); + }); + + it("function with two minima", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(-2)).closeTo(1, 1e-12); + expect(f(2)).closeTo(1, 1e-12); + expect(f(0)).closeTo(2, 1e-12); + // like parabola to left of minimum + expect(f(-3)).closeTo(1 + 1, 1e-12); + expect(f(-4)).closeTo(4 + 1, 1e-12); + expect(f(-5)).closeTo(9 + 1, 1e-12); + // like parabola to right of minimum + expect(f(3)).closeTo(1 + 1, 1e-12); + expect(f(4)).closeTo(4 + 1, 1e-12); + expect(f(5)).closeTo(9 + 1, 1e-12); + }); + + it("function with two minima and maximum with specified height", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(-2)).closeTo(1, 1e-12); + expect(f(2)).closeTo(1, 1e-12); + expect(f(0)).closeTo(5, 1e-12); + // like parabola to left of minimum + expect(f(-3)).closeTo(1 + 1, 1e-12); + expect(f(-4)).closeTo(4 + 1, 1e-12); + expect(f(-5)).closeTo(9 + 1, 1e-12); + // like parabola to right of minimum + expect(f(3)).closeTo(1 + 1, 1e-12); + expect(f(4)).closeTo(4 + 1, 1e-12); + expect(f(5)).closeTo(9 + 1, 1e-12); + }); + + it("function with two minima and extremum with specified height", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(-2)).closeTo(1, 1e-12); + expect(f(2)).closeTo(1, 1e-12); + expect(f(0)).closeTo(5, 1e-12); + // like parabola to left of minimum + expect(f(-3)).closeTo(1 + 1, 1e-12); + expect(f(-4)).closeTo(4 + 1, 1e-12); + expect(f(-5)).closeTo(9 + 1, 1e-12); + // like parabola to right of minimum + expect(f(3)).closeTo(1 + 1, 1e-12); + expect(f(4)).closeTo(4 + 1, 1e-12); + expect(f(5)).closeTo(9 + 1, 1e-12); + }); + + it("function with maximum and higher minimum", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(-2)).closeTo(1, 1e-12); + expect(f(-3)).closeTo(0, 1e-12); + expect(f(-2 + 4 / 3)).closeTo(0, 1e-12); + + expect(f(2)).closeTo(2, 1e-12); + expect(f(3)).closeTo(3, 1e-12); + expect(f(2 - 4 / 3)).closeTo(3, 1e-12); + + expect(f(0)).closeTo(1.5, 1e-12); + }); + + it("function with maximum and higher extremum", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(-2)).closeTo(1, 1e-12); + expect(f(-3)).closeTo(0, 1e-12); + expect(f(0)).closeTo(0, 1e-12); + + expect(f(2)).closeTo(2, 1e-12); + expect(f(3)).closeTo(1, 1e-12); + }); + + it("function with minimum and lower maximum", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(-2)).closeTo(3, 1e-12); + expect(f(-3)).closeTo(4, 1e-12); + expect(f(-2 + 4 / 3)).closeTo(4, 1e-12); + + expect(f(2)).closeTo(2, 1e-12); + expect(f(3)).closeTo(1, 1e-12); + expect(f(2 - 4 / 3)).closeTo(1, 1e-12); + + expect(f(0)).closeTo(2.5, 1e-12); + }); + + it("function with minimum and lower extremum", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(-2)).closeTo(3, 1e-12); + expect(f(-3)).closeTo(4, 1e-12); + expect(f(0)).closeTo(4, 1e-12); + + expect(f(2)).closeTo(2, 1e-12); + expect(f(3)).closeTo(3, 1e-12); + }); + + it("function with extremum and lower maximum", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(-2)).closeTo(3, 1e-12); + expect(f(-3)).closeTo(2, 1e-12); + expect(f(0)).closeTo(1, 1e-12); + + expect(f(2)).closeTo(2, 1e-12); + expect(f(3)).closeTo(1, 1e-12); + }); + + it("functions with copied extrema that overwrite attributes", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(3)).closeTo(-2, 1e-12); + expect(f(5)).closeTo(-2, 1e-12); + + expect(f(2)).closeTo(-3, 1e-12); + expect(f(4)).closeTo(-3, 1e-12); + expect(f(6)).closeTo(-3, 1e-12); + + let g = await core.components!["/g"].state.numericalf.value; + + expect(g(3)).closeTo(2, 1e-12); + expect(g(5)).closeTo(-2, 1e-12); + + expect(g(2)).closeTo(1, 1e-12); + expect(g(4)).closeTo(0, 1e-12); + expect(g(6)).closeTo(-1, 1e-12); + }); + + it("copy function and overwrite extrema", async () => { + let core = await createTestCore({ + doenetML: ` + + + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(2)).closeTo(3, 1e-12); + expect(f(4)).closeTo(4, 1e-12); + + expect(f(1)).closeTo(4, 1e-12); + expect(f(3)).closeTo(3.5, 1e-12); + expect(f(5)).closeTo(3, 1e-12); + + let g = await core.components!["/g"].state.numericalf.value; + + expect(g(0)).closeTo(4, 1e-12); + expect(g(2)).closeTo(3, 1e-12); + + expect(g(-1)).closeTo(3, 1e-12); + expect(g(1)).closeTo(3.5, 1e-12); + expect(g(3)).closeTo(4, 1e-12); + + let h = await core.components!["/h"].state.numericalf.value; + + expect(h(4)).closeTo(4, 1e-12); + expect(h(6)).closeTo(3, 1e-12); + + expect(h(3)).closeTo(3, 1e-12); + expect(h(5)).closeTo(3.5, 1e-12); + expect(h(7)).closeTo(4, 1e-12); + }); + + it("function with maximum through points", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(-2)).closeTo(2, 1e-12); + expect(f(-5)).closeTo(0, 1e-12); + expect(f(-6)).closeTo(-1, 1e-12); + + // extrapolates linearly + let slope = f(-6) - f(-7); + expect(f(-8)).closeTo(-1 - slope * 2, 1e-12); + expect(f(-9)).closeTo(-1 - slope * 3, 1e-12); + expect(f(-10)).closeTo(-1 - slope * 4, 1e-12); + + expect(f(0)).closeTo(0, 1e-12); + expect(f(1)).closeTo(0, 1e-12); + // extrapolates linearly + expect(f(2)).closeTo(0, 1e-12); + expect(f(3)).closeTo(0, 1e-12); + }); + + it("function with single through point", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(-6)).closeTo(-1, 1e-12); + expect(f(-2)).closeTo(-1, 1e-12); + expect(f(-12)).closeTo(-1, 1e-12); + expect(f(12)).closeTo(-1, 1e-12); + }); + + it("function with single through point with slope", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(-6)).closeTo(-1, 1e-12); + expect(f(-2)).closeTo(-1 + 3 * (-2 + 6), 1e-12); + expect(f(-12)).closeTo(-1 + 3 * (-12 + 6), 1e-12); + expect(f(12)).closeTo(-1 + 3 * (12 + 6), 1e-12); + }); + + it("function with single through point with dynamic slope", async () => { + let core = await createTestCore({ + doenetML: ` +

slope:

+ + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(-6)).closeTo(-1, 1e-12); + expect(f(-2)).closeTo(-1 + 0 * (-2 + 6), 1e-12); + expect(f(-12)).closeTo(-1 + 0 * (-12 + 6), 1e-12); + expect(f(12)).closeTo(-1 + 0 * (12 + 6), 1e-12); + + await updateMathInputValue({ latex: "2", componentName: "/mi", core }); + f = await core.components!["/f"].state.numericalf.value; + + expect(f(-6)).closeTo(-1, 1e-12); + expect(f(-2)).closeTo(-1 + 2 * (-2 + 6), 1e-12); + expect(f(-12)).closeTo(-1 + 2 * (-12 + 6), 1e-12); + expect(f(12)).closeTo(-1 + 2 * (12 + 6), 1e-12); + + await updateMathInputValue({ latex: "-3", componentName: "/mi", core }); + f = await core.components!["/f"].state.numericalf.value; + + expect(f(-6)).closeTo(-1, 1e-12); + expect(f(-2)).closeTo(-1 - 3 * (-2 + 6), 1e-12); + expect(f(-12)).closeTo(-1 - 3 * (-12 + 6), 1e-12); + expect(f(12)).closeTo(-1 - 3 * (12 + 6), 1e-12); + + await updateMathInputValue({ latex: "", componentName: "/mi", core }); + f = await core.components!["/f"].state.numericalf.value; + + expect(f(-6)).closeTo(-1, 1e-12); + expect(f(-2)).closeTo(-1 + 0 * (-2 + 6), 1e-12); + expect(f(-12)).closeTo(-1 + 0 * (-12 + 6), 1e-12); + expect(f(12)).closeTo(-1 + 0 * (12 + 6), 1e-12); + }); + + it("function with two through points with dynamic slope", async () => { + let core = await createTestCore({ + doenetML: ` +

slope:

+ + `, + }); + + // with undefined slope, get line through points + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(-6)).closeTo(-1, 1e-12); + expect(f(-2)).closeTo(-1 + 1 * (-2 + 6), 1e-12); + expect(f(-12)).closeTo(-1 + 1 * (-12 + 6), 1e-12); + expect(f(12)).closeTo(-1 + 1 * (12 + 6), 1e-12); + + await updateMathInputValue({ latex: "2", componentName: "/mi", core }); + f = await core.components!["/f"].state.numericalf.value; + + expect(f(-6 - 0.01)).closeTo(-1 - 0.01 * 2, 1e-3); + expect(f(-6)).closeTo(-1, 1e-12); + expect(f(-6 + 0.01)).closeTo(-1 + 0.01 * 2, 1e-3); + + expect(f(3 - 0.01)).closeTo(8 - 0.01 * 2, 1e-3); + expect(f(3)).closeTo(8, 1e-12); + expect(f(3 + 0.01)).closeTo(8 + 0.01 * 2, 1e-3); + + // extrapolate linearly + expect(f(-6 - 3)).closeTo(-1 - 3 * 2, 1e-12); + expect(f(3 + 3)).closeTo(8 + 3 * 2, 1e-12); + + await updateMathInputValue({ latex: "-3", componentName: "/mi", core }); + f = await core.components!["/f"].state.numericalf.value; + + expect(f(-6 - 0.01)).closeTo(-1 - 0.01 * -3, 1e-3); + expect(f(-6)).closeTo(-1, 1e-12); + expect(f(-6 + 0.01)).closeTo(-1 + 0.01 * -3, 1e-3); + + expect(f(3 - 0.01)).closeTo(8 - 0.01 * -3, 1e-3); + expect(f(3)).closeTo(8, 1e-12); + expect(f(3 + 0.01)).closeTo(8 + 0.01 * -3, 1e-3); + + // extrapolate linearly + expect(f(-6 - 3)).closeTo(-1 - 3 * -3, 1e-12); + expect(f(3 + 3)).closeTo(8 + 3 * -3, 1e-12); + + await updateMathInputValue({ latex: "", componentName: "/mi", core }); + f = await core.components!["/f"].state.numericalf.value; + + expect(f(-6)).closeTo(-1, 1e-12); + expect(f(-2)).closeTo(-1 + 1 * (-2 + 6), 1e-12); + expect(f(-12)).closeTo(-1 + 1 * (-12 + 6), 1e-12); + expect(f(12)).closeTo(-1 + 1 * (12 + 6), 1e-12); + }); + + it("function through three points", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(0)).closeTo(2, 1e-12); + expect(f(2)).closeTo(1, 1e-12); + expect(f(3)).closeTo(2, 1e-12); + // extrapolate linearly + let slope = f(4) - f(3); + expect(f(5)).closeTo(2 + slope * 2, 1e-12); + expect(f(6)).closeTo(2 + slope * 3, 1e-12); + expect(f(7)).closeTo(2 + slope * 4, 1e-12); + slope = f(0) - f(-1); + expect(f(-2)).closeTo(2 - slope * 2, 1e-12); + expect(f(-3)).closeTo(2 - slope * 3, 1e-12); + expect(f(-4)).closeTo(2 - slope * 4, 1e-12); + }); + + it("function through three points, label with math", async () => { + let core = await createTestCore({ + doenetML: ` + + + +
+ `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(0)).closeTo(2, 1e-12); + expect(f(2)).closeTo(1, 1e-12); + expect(f(3)).closeTo(2, 1e-12); + // extrapolate linearly + let slope = f(4) - f(3); + expect(f(5)).closeTo(2 + slope * 2, 1e-12); + expect(f(6)).closeTo(2 + slope * 3, 1e-12); + expect(f(7)).closeTo(2 + slope * 4, 1e-12); + slope = f(0) - f(-1); + expect(f(-2)).closeTo(2 - slope * 2, 1e-12); + expect(f(-3)).closeTo(2 - slope * 3, 1e-12); + expect(f(-4)).closeTo(2 - slope * 4, 1e-12); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/f"].stateValues.label).eq("\\(\\int f\\)"); + }); + + it("function through three points with slopes", async () => { + let core = await createTestCore({ + doenetML: ` + (2,1) + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(-0.01)).closeTo(2 - 0.01 * 0.5, 1e-3); + expect(f(0)).closeTo(2, 1e-12); + expect(f(0.01)).closeTo(2 + 0.01 * 0.5, 1e-3); + + expect(f(2 - 0.01)).closeTo(1 - 0.01 * 2, 1e-3); + expect(f(2)).closeTo(1, 1e-12); + expect(f(2 + 0.01)).closeTo(1 + 0.01 * 2, 1e-3); + + expect(f(3 - 0.01)).closeTo(2 - 0.01 * -1, 1e-3); + expect(f(3)).closeTo(2, 1e-12); + expect(f(3 + 0.01)).closeTo(2 + 0.01 * -1, 1e-3); + + // extrapolate linearly + let slope = -1; + expect(f(5)).closeTo(2 + slope * 2, 1e-12); + expect(f(6)).closeTo(2 + slope * 3, 1e-12); + expect(f(7)).closeTo(2 + slope * 4, 1e-12); + slope = 0.5; + expect(f(-2)).closeTo(2 - slope * 2, 1e-12); + expect(f(-3)).closeTo(2 - slope * 3, 1e-12); + expect(f(-4)).closeTo(2 - slope * 4, 1e-12); + }); + + it("function with conflicting points", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + expect(f(0)).eqls(NaN); + expect(f(1)).eqls(NaN); + expect(f(2)).eqls(NaN); + + // calculate line/char begin on all warnings + core.postErrorWarnings(); + + let errorWarnings = core.errorWarnings; + + expect(errorWarnings.errors.length).eq(0); + expect(errorWarnings.warnings.length).eq(1); + + expect(errorWarnings.warnings[0].message).contain( + `Function contains two points with locations too close together. Can't define function`, + ); + expect(errorWarnings.warnings[0].level).eq(1); + expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(2); + expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(5); + expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(2); + expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(53); + }); + + it("function with non-numerical points and slope", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + let fleft = (x) => 6 - (x - 5) ** 2 / 4; + let fright = (x) => 6 - (x - 5) ** 2; + expect(f(5)).closeTo(6, 1e-12); + expect(f(1)).closeTo(2, 1e-12); + expect(f(-2)).closeTo(fleft(-2), 1e-12); + expect(f(7)).closeTo(fright(7), 1e-12); + + // calculate line/char begin on all warnings + core.postErrorWarnings(); + + let errorWarnings = core.errorWarnings; + + expect(errorWarnings.errors.length).eq(0); + expect(errorWarnings.warnings.length).eq(5); + + expect(errorWarnings.warnings[0].message).contain( + `Ignoring non-numerical maximum of function`, + ); + expect(errorWarnings.warnings[0].level).eq(1); + expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(2); + expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(5); + expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(2); + expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(118); + + expect(errorWarnings.warnings[1].message).contain( + `Ignoring non-numerical minimum of function`, + ); + expect(errorWarnings.warnings[1].level).eq(1); + expect(errorWarnings.warnings[1].doenetMLrange.lineBegin).eq(2); + expect(errorWarnings.warnings[1].doenetMLrange.charBegin).eq(5); + expect(errorWarnings.warnings[1].doenetMLrange.lineEnd).eq(2); + expect(errorWarnings.warnings[1].doenetMLrange.charEnd).eq(118); + + expect(errorWarnings.warnings[2].message).contain( + `Ignoring non-numerical extremum of function`, + ); + expect(errorWarnings.warnings[2].level).eq(1); + expect(errorWarnings.warnings[2].doenetMLrange.lineBegin).eq(2); + expect(errorWarnings.warnings[2].doenetMLrange.charBegin).eq(5); + expect(errorWarnings.warnings[2].doenetMLrange.lineEnd).eq(2); + expect(errorWarnings.warnings[2].doenetMLrange.charEnd).eq(118); + + expect(errorWarnings.warnings[3].message).contain( + `Ignoring non-numerical slope of function`, + ); + expect(errorWarnings.warnings[3].level).eq(1); + expect(errorWarnings.warnings[3].doenetMLrange.lineBegin).eq(2); + expect(errorWarnings.warnings[3].doenetMLrange.charBegin).eq(5); + expect(errorWarnings.warnings[3].doenetMLrange.lineEnd).eq(2); + expect(errorWarnings.warnings[3].doenetMLrange.charEnd).eq(118); + + expect(errorWarnings.warnings[4].message).contain( + `Ignoring non-numerical point of function`, + ); + expect(errorWarnings.warnings[4].level).eq(1); + expect(errorWarnings.warnings[4].doenetMLrange.lineBegin).eq(2); + expect(errorWarnings.warnings[4].doenetMLrange.charBegin).eq(5); + expect(errorWarnings.warnings[4].doenetMLrange.lineEnd).eq(2); + expect(errorWarnings.warnings[4].doenetMLrange.charEnd).eq(118); + }); + + it("function with empty maximum", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + let factual = (x) => (x - 4) ** 2; + expect(f(4)).closeTo(0, 1e-12); + expect(f(-2)).closeTo(factual(-2), 1e-12); + expect(f(7)).closeTo(factual(7), 1e-12); + + // calculate line/char begin on all warnings + core.postErrorWarnings(); + + let errorWarnings = core.errorWarnings; + + expect(errorWarnings.errors.length).eq(0); + expect(errorWarnings.warnings.length).eq(1); + + expect(errorWarnings.warnings[0].message).contain( + `Ignoring empty maximum of function`, + ); + expect(errorWarnings.warnings[0].level).eq(1); + expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(2); + expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(7); + expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(2); + expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(54); + }); + + it("copy function and overwrite through points and slopes", async () => { + let core = await createTestCore({ + doenetML: ` + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + let f = createFunctionFromDefinition( + stateVariables["/f"].stateValues.fDefinitions[0], + ); + expect(f(0)).closeTo(2, 1e-12); + expect(f(2)).closeTo(1, 1e-12); + expect(f(3)).closeTo(2, 1e-12); + // extrapolate linearly + let slope = f(4) - f(3); + expect(f(5)).closeTo(2 + slope * 2, 1e-12); + expect(f(6)).closeTo(2 + slope * 3, 1e-12); + expect(f(7)).closeTo(2 + slope * 4, 1e-12); + slope = f(0) - f(-1); + expect(f(-2)).closeTo(2 - slope * 2, 1e-12); + expect(f(-3)).closeTo(2 - slope * 3, 1e-12); + expect(f(-4)).closeTo(2 - slope * 4, 1e-12); + + let g = createFunctionFromDefinition( + stateVariables["/g"].stateValues.fDefinitions[0], + ); + expect(g(1)).closeTo(5, 1e-12); + expect(g(4)).closeTo(2, 1e-12); + // linear function + slope = g(1) - g(0); + expect(g(2)).closeTo(5 + slope * 1, 1e-12); + expect(g(3)).closeTo(5 + slope * 2, 1e-12); + expect(g(4)).closeTo(5 + slope * 3, 1e-12); + expect(g(0)).closeTo(5 + slope * -1, 1e-12); + expect(g(-1)).closeTo(5 + slope * -2, 1e-12); + expect(g(-2)).closeTo(5 + slope * -3, 1e-12); + + let h = createFunctionFromDefinition( + stateVariables["/h"].stateValues.fDefinitions[0], + ); + expect(h(0)).closeTo(2, 1e-12); + expect(h(2)).closeTo(1, 1e-12); + expect(h(3)).closeTo(2, 1e-12); + // extrapolate linearly at given slopes + slope = -3; + expect(h(5)).closeTo(2 + slope * 2, 1e-12); + expect(h(6)).closeTo(2 + slope * 3, 1e-12); + expect(h(7)).closeTo(2 + slope * 4, 1e-12); + slope = 1; + expect(h(-2)).closeTo(2 - slope * 2, 1e-12); + expect(h(-3)).closeTo(2 - slope * 3, 1e-12); + expect(h(-4)).closeTo(2 - slope * 4, 1e-12); + // close to given slope near middle point + slope = 2; + expect(h(2.0001)).closeTo(1 + slope * 0.0001, 1e-7); + expect(h(1.9999)).closeTo(1 + slope * -0.0001, 1e-7); + }); + + it("check monotonicity", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + for (let x = -5; x <= 6; x += 0.1) { + expect(f(x - 0.1)).lessThan(f(x)); + } + expect(f(-5)).closeTo(0, 1e-12); + expect(f(-4)).closeTo(0.1, 1e-12); + expect(f(-3)).closeTo(0.3, 1e-12); + expect(f(-2)).closeTo(3, 1e-12); + expect(f(-1)).closeTo(3.1, 1e-12); + expect(f(0)).closeTo(3.2, 1e-12); + expect(f(1)).closeTo(5, 1e-12); + expect(f(6)).closeTo(6, 1e-12); + expect(f(7)).closeTo(5, 1e-12); + expect(f(8)).closeTo(2, 1e-12); + }); + + it("point constrained to function", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + $f + + +
+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let p = stateVariables["/P"]; + + 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); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -8, y: 8 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + p = stateVariables["/P"]; + + // @ts-ignore + x = constantFromAst(p.stateValues.xs[0]); + // @ts-ignore + y = constantFromAst(p.stateValues.xs[1]); + + expect(6 - ((x - 5) * (x - 5)) / 25).closeTo(y, 1e-5); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 8, y: 8 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + p = stateVariables["/P"]; + + // @ts-ignore + x = constantFromAst(p.stateValues.xs[0]); + // @ts-ignore + y = constantFromAst(p.stateValues.xs[1]); + + expect(6 - (x - 5) * (x - 5) * (2 / 9)).closeTo(y, 1e-5); + }); + + it("point constrained to function, symbolic initial x", async () => { + let core = await createTestCore({ + doenetML: ` + x^2 + + + + $f + + + +
+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let p = stateVariables["/P"]; + + expect(constantFromAst(p.stateValues.xs[0])).closeTo( + Math.sqrt(2), + 1e-6, + ); + expect(constantFromAst(p.stateValues.xs[1])).closeTo(2, 1e-6); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -2, y: 2 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + p = stateVariables["/P"]; + + 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 () => { + let core = await createTestCore({ + doenetML: ` + + + + + $f + + +
+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let p = stateVariables["/P"]; + + 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); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -8, y: 8 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + p = stateVariables["/P"]; + + 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); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 6, y: 8 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + p = stateVariables["/P"]; + + 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); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 8, y: -4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + p = stateVariables["/P"]; + + 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); + }); + + it("point constrained to function, restrict to open domain", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + $f + + +
+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let p = stateVariables["/P"]; + + 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); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -8, y: 8 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + p = stateVariables["/P"]; + + x = constantFromAst(p.stateValues.xs[0]); + y = constantFromAst(p.stateValues.xs[1]); + + expect(x).greaterThan(-4 + 1e-12); + expect(x).lessThan(-4 + 1e-3); + expect(6 - ((x - 5) * (x - 5)) / 25).closeTo(y, 1e-5); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 6, y: 8 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + p = stateVariables["/P"]; + + 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); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 8, y: -4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + p = stateVariables["/P"]; + + x = constantFromAst(p.stateValues.xs[0]); + y = constantFromAst(p.stateValues.xs[1]); + + expect(x).lessThan(7 - 1e-12); + expect(x).greaterThan(7 - 1e-3); + expect(6 - (x - 5) * (x - 5) * (2 / 9)).closeTo(y, 1e-5); + }); + + async function test_point_constrained_function_implicit_domain(core) { + let f = (x) => Math.sqrt(x) * Math.sqrt(5 - x); + + let stateVariables = await returnAllStateVariables(core); + + let p = stateVariables["/P"]; + 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", + componentName: "/P", + args: { x: -1, y: 8 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + p = stateVariables["/P"]; + + let x = constantFromAst(p.stateValues.xs[0]); + let y = constantFromAst(p.stateValues.xs[1]); + + expect(y).closeTo(f(x), 1e-6); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 6, y: 8 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + p = stateVariables["/P"]; + + x = constantFromAst(p.stateValues.xs[0]); + y = constantFromAst(p.stateValues.xs[1]); + + expect(y).closeTo(f(x), 1e-6); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 8, y: -4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + p = stateVariables["/P"]; + + x = constantFromAst(p.stateValues.xs[0]); + y = constantFromAst(p.stateValues.xs[1]); + + expect(y).closeTo(f(x), 1e-6); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -1, y: -6 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + p = stateVariables["/P"]; + + x = constantFromAst(p.stateValues.xs[0]); + y = constantFromAst(p.stateValues.xs[1]); + + expect(y).closeTo(f(x), 1e-6); + } + + it("point constrained to function with restricted domain, not explicit", async () => { + let core = await createTestCore({ + doenetML: ` + sqrt(x)sqrt(5-x) + + + + $f + + + + `, + }); + + await test_point_constrained_function_implicit_domain(core); + }); + + it("point constrained to function with restricted domain in graph, not explicit", async () => { + let core = await createTestCore({ + doenetML: ` + + sqrt(x)sqrt(5-x) + + + + $f + + + + + `, + }); + + await test_point_constrained_function_implicit_domain(core); + }); + + async function test_function_3_over_exp(core) { + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/f"].stateValues.numInputs).eq(1); + + const numericalf = await core.components!["/f"].state.numericalf.value; + const symbolicf = ( + await core.components!["/f"].state.symbolicfs.value + )[0]; + + expect(numericalf(-5)).closeTo(3 / (1 + Math.exp(5 / 2)), 1e-12); + expect(numericalf(1)).closeTo(3 / (1 + Math.exp(-1 / 2)), 1e-12); + expect( + symbolicf(me.fromAst(-5)).equals(me.fromText("3/(1+e^(5/2))")), + ).eq(true); + expect( + symbolicf(me.fromAst(1)).equals(me.fromText("3/(1+e^(-1/2))")), + ).eq(true); + expect( + symbolicf(me.fromAst("z")).equals(me.fromText("3/(1+e^(-z/2))")), + ).eq(true); + + expect( + me + .fromAst(stateVariables["/fz"].stateValues.value.tree) + .equals(me.fromText("3/(1+e^(-z/2))")), + ).eq(true); + } + + it("function determined by formula via sugar", async () => { + let core = await createTestCore({ + doenetML: ` + + 3/(1+e^(-x/2)) + + + + + `, + }); + + await test_function_3_over_exp(core); + }); + + it("function determined by formula via sugar, label with math", async () => { + let core = await createTestCore({ + doenetML: ` + + 3/(1+e^(-x/2)) + + + + + `, + }); + + await test_function_3_over_exp(core); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/f"].stateValues.label).eq( + "Hello \\(\\frac{3}{1 + e^{-\\frac{x}{2}}}\\)", + ); + }); + + it("function determined by formula via sugar, with strings and macros", async () => { + let core = await createTestCore({ + doenetML: ` + + $a/(1+e^(-x/$b)) + + 3 + 2 + + + `, + }); + + await test_function_3_over_exp(core); + }); + + it("function determined by formula via sugar, with strings and maths", async () => { + let core = await createTestCore({ + doenetML: ` + + 3/(1+e^(-x/2)) + + + + `, + }); + + await test_function_3_over_exp(core); + }); + + it("function determined by math formula", async () => { + let core = await createTestCore({ + doenetML: ` + 3/(1+e^(-x/2)) + + + `, + }); + + await test_function_3_over_exp(core); + }); + + it("function determined by math formula, label with math", async () => { + let core = await createTestCore({ + doenetML: ` + + + 3/(1+e^(-x/2)) + + + + `, + }); + + await test_function_3_over_exp(core); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/f"].stateValues.label).eq( + "Hello \\(\\frac{3}{1 + e^{-\\frac{x}{2}}}\\)", + ); + }); + + it("function determined by math formula, with macros", async () => { + let core = await createTestCore({ + doenetML: ` + + $a/(1+e^(-x/$b)) + + 3 + 2 + + + `, + }); + + await test_function_3_over_exp(core); + }); + + async function test_function_squared_time_sin(core) { + const numericalf = await core.components!["/f"].state.numericalf.value; + const symbolicf = ( + await core.components!["/f"].state.symbolicfs.value + )[0]; + + expect(numericalf(-5)).closeTo( + (25 * Math.sin(0.5 * Math.PI * -5)) / 100, + 1e-12, + ); + expect(numericalf(3)).closeTo( + (9 * Math.sin(0.5 * Math.PI * 3)) / 100, + 1e-12, + ); + expect( + symbolicf(me.fromAst(-5)).equals( + me.fromText("(-5)^2sin(pi(-5)/2)/100"), + ), + ).eq(true); + expect( + symbolicf(me.fromAst(3)).equals( + me.fromText("(3)^2sin(pi(3)/2)/100"), + ), + ).eq(true); + expect( + symbolicf(me.fromAst("p")).equals( + me.fromText("p^2sin(pi p/2)/100"), + ), + ).eq(true); + } + + it("function determined by sugar formula in different variable", async () => { + let core = await createTestCore({ + doenetML: ` + + q^2 sin(pi q/2)/100 + + + `, + }); + + await test_function_squared_time_sin(core); + }); + + it("function determined by sugar formula in different variable, with strings and macros", async () => { + let core = await createTestCore({ + doenetML: ` + + $var^$c sin(pi $var/$c)/$d + + + q + 2 + 100 + `, + }); + + await test_function_squared_time_sin(core); + }); + + it("function determined by math formula in different variable", async () => { + let core = await createTestCore({ + doenetML: ` + q^2 sin(pi q/2)/100 + `, + }); + + await test_function_squared_time_sin(core); + }); + + it("function with empty variables attribute", async () => { + let core = await createTestCore({ + doenetML: ` + + x^2 sin(pi x/2)/100 + + `, + }); + + await test_function_squared_time_sin(core); + }); + + it("function determined by function", async () => { + let core = await createTestCore({ + doenetML: ` + q^2 sin(pi q/2)/100 + + $f0 + + `, + }); + + await test_function_squared_time_sin(core); + }); + + it("function determined by function, label with math", async () => { + let core = await createTestCore({ + doenetML: ` + q^2 sin(pi q/2)/100 + + $f0 + + + `, + }); + + await test_function_squared_time_sin(core); + + let stateVariables = await returnAllStateVariables(core); + + expect( + stateVariables["/f"].stateValues.label + .replaceAll("\\,", "") + .replaceAll(" ", ""), + ).eq("\\(\\frac{q^{2}\\sin\\left(\\frac{\\piq}{2}\\right)}{100}\\)"); + }); + + it("warnings for bad variable or variable attribute", async () => { + let core = await createTestCore({ + doenetML: ` + x + x + `, + }); + + let errorWarnings = core.errorWarnings; + + expect(errorWarnings.errors.length).eq(0); + expect(errorWarnings.warnings.length).eq(2); + + expect(errorWarnings.warnings[0].message).contain( + `Invalid value of a variable: cos(x)`, + ); + expect(errorWarnings.warnings[0].level).eq(1); + expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(3); + expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(25); + expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(3); + expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(30); + + expect(errorWarnings.warnings[1].message).contain( + `Invalid value of a variable: sin(x)`, + ); + expect(errorWarnings.warnings[1].level).eq(1); + expect(errorWarnings.warnings[1].doenetMLrange.lineBegin).eq(2); + expect(errorWarnings.warnings[1].doenetMLrange.charBegin).eq(26); + expect(errorWarnings.warnings[1].doenetMLrange.lineEnd).eq(2); + expect(errorWarnings.warnings[1].doenetMLrange.charEnd).eq(31); + }); + + it("point constrained to function in different variable", async () => { + let core = await createTestCore({ + doenetML: ` + + log(2u) + + + + $f + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let p = stateVariables["/P"]; + + let x = constantFromAst(p.stateValues.xs[0]); + let y = constantFromAst(p.stateValues.xs[1]); + + expect(Math.log(2 * x)).closeTo(y, 1e-5); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 8, y: 8 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + p = stateVariables["/P"]; + + x = constantFromAst(p.stateValues.xs[0]); + y = constantFromAst(p.stateValues.xs[1]); + + expect(Math.log(2 * x)).closeTo(y, 1e-5); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -8, y: -8 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + p = stateVariables["/P"]; + + x = constantFromAst(p.stateValues.xs[0]); + y = constantFromAst(p.stateValues.xs[1]); + + expect(Math.log(2 * x)).closeTo(y, 1e-5); + }); + + it("point constrained to function in different variable, restrict left-open domain", async () => { + let core = await createTestCore({ + doenetML: ` + + log(2u) + + + + $f + + + +
+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let p = stateVariables["/P"]; + + 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); + expect(Math.log(2 * x)).closeTo(y, 1e-5); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 4, y: 6 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + p = stateVariables["/P"]; + + 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); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 8, y: 8 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + p = stateVariables["/P"]; + + 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); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -8, y: -8 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + p = stateVariables["/P"]; + + 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); + expect(Math.log(2 * x)).closeTo(y, 1e-5); + }); + + it("point constrained to function in different variable, restrict right-open domain", async () => { + let core = await createTestCore({ + doenetML: ` + + log(2u) + + + + $f + + + +
+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let p = stateVariables["/P"]; + + 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); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 4, y: 6 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + p = stateVariables["/P"]; + + 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); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 8, y: 8 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + p = stateVariables["/P"]; + + x = constantFromAst(p.stateValues.xs[0]); + y = constantFromAst(p.stateValues.xs[1]); + + expect(x).lessThan(6 - 1e-12); + expect(x).greaterThan(6 - 1e-3); + expect(Math.log(2 * x)).closeTo(y, 1e-5); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -8, y: -8 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + p = stateVariables["/P"]; + + 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); + }); + + async function check_extrema({ + core, + maxima, + minima, + haveGlobalMax = false, + globalsup, + haveGlobalMin = false, + globalinf, + globalsupLargerThan, + globalinfSmallerThan, + globalsupLocation, + globalinfLocation, + fName = "/f", + }: { + core: any; + maxima: number[][]; + minima: number[][]; + haveGlobalMax?: boolean; + globalsup?: number; + haveGlobalMin?: boolean; + globalinf?: number; + globalsupLargerThan?: number; + globalinfSmallerThan?: number; + globalsupLocation?: number; + globalinfLocation?: number; + fName?: string; + }) { + const extrema = [...maxima, ...minima].sort((a, b) => a[0] - b[0]); + + const stateVariables = await returnAllStateVariables(core); + const fState = stateVariables[fName].stateValues; + + expect(fState.numMaxima).eq(maxima.length); + let foundMaxima = fState.maxima; + for (let [i, max] of maxima.entries()) { + for (let [j, val] of max.entries()) { + expect(foundMaxima[i][j]).closeTo(val, 1e-3); + } + } + expect(fState.numMinima).eq(minima.length); + let foundMinima = fState.minima; + for (let [i, min] of minima.entries()) { + for (let [j, val] of min.entries()) { + expect(foundMinima[i][j]).closeTo(val, 1e-3); + } + } + + expect(fState.numExtrema).eq(extrema.length); + + let foundExtrema = fState.extrema; + for (let [i, extr] of extrema.entries()) { + for (let [j, val] of extr.entries()) { + expect(foundExtrema[i][j]).closeTo(val, 1e-3); + } + } + + if (globalsupLargerThan !== undefined) { + expect(fState.globalSupremum[1]).greaterThan(globalsupLargerThan); + if (haveGlobalMax) { + expect(fState.globalMaximum[1]).eq(fState.globalSupremum[1]); + } else { + expect(fState.globalMaximum).eqls([]); + } + } else { + if (globalsup === undefined) { + expect(fState.globalSupremum).eqls([]); + expect(fState.globalMaximum).eqls([]); + } else if (Number.isFinite(globalsup)) { + expect(fState.globalSupremum[1]).closeTo(globalsup, 1e-3); + if (haveGlobalMax) { + expect(fState.globalMaximum[1]).closeTo(globalsup, 1e-3); + } else { + expect(fState.globalMaximum).eqls([]); + } + } else { + expect(fState.globalSupremum[1]).eq(globalsup); + expect(fState.globalMaximum).eqls([]); + } + } + + if (globalinfSmallerThan !== undefined) { + expect(fState.globalInfimum[1]).lessThan(globalinfSmallerThan); + if (haveGlobalMin) { + expect(fState.globalMinimum[1]).eq(fState.globalInfimum[1]); + } else { + expect(fState.globalMinimum).eqls([]); + } + } else { + if (globalinf === undefined) { + expect(fState.globalInfimum).eqls([]); + expect(fState.globalMinimum).eqls([]); + } else if (Number.isFinite(globalinf)) { + expect(fState.globalInfimum[1]).closeTo(globalinf, 1e-3); + if (haveGlobalMin) { + expect(fState.globalMinimum[1]).closeTo(globalinf, 1e-3); + } else { + expect(fState.globalMinimum).eqls([]); + } + } else { + expect(fState.globalInfimum[1]).eq(globalinf); + expect(fState.globalMinimum).eqls([]); + } + } + if (globalsupLocation !== undefined) { + if (Number.isFinite(globalsupLocation)) { + expect(fState.globalSupremum[0]).closeTo( + globalsupLocation, + 1e-3, + ); + } else { + expect(fState.globalSupremum[0]).eq(globalsupLocation); + } + } + if (globalinfLocation !== undefined) { + if (Number.isFinite(globalinfLocation)) { + expect(fState.globalInfimum[0]).closeTo( + globalinfLocation, + 1e-3, + ); + } else { + expect(fState.globalInfimum[0]).eq(globalinfLocation); + } + } + } + + it("calculated extrema from spline", async () => { + let core = await createTestCore({ + doenetML: ` + (0.7, 5.43) + (3,4) + (5,6) + (-5,6) + + `, + }); + + await check_extrema({ + core, + maxima: [ + [-2.15, 7], + [5, 6], + ], + minima: [ + [-5, 6], + [3, 4], + ], + globalsup: Infinity, + globalinf: -Infinity, + }); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P1", + args: { x: 2, y: 2 }, + event: null, + }); + + await check_extrema({ + core, + maxima: [ + [-1.5, 7], + [5, 6], + ], + minima: [ + [-5, 6], + [2, 2], + ], + globalsup: Infinity, + globalinf: -Infinity, + }); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P1", + args: { x: 3.6, y: 5.1 }, + event: null, + }); + + await check_extrema({ + core, + maxima: [ + [-1, 7], + [3.6, 5.1], + [5, 6], + ], + minima: [ + [-5, 6], + [3, 4], + [4.3, 5], + ], + globalsup: Infinity, + globalinf: -Infinity, + }); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P1", + args: { x: 8, y: 9 }, + event: null, + }); + + await check_extrema({ + core, + maxima: [ + [-1, 7], + [5, 6], + ], + minima: [ + [-5, 6], + [3, 4], + [6.5, 5], + ], + globalsup: Infinity, + globalinf: 4, + haveGlobalMin: true, + }); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P1", + args: { x: 5, y: 2 }, + event: null, + }); + + await check_extrema({ core, maxima: [], minima: [] }); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P1", + args: { x: -9, y: 0 }, + event: null, + }); + + await check_extrema({ + core, + maxima: [ + [-7, 7], + [-1, 7], + [5, 6], + ], + minima: [ + [-5, 6], + [3, 4], + ], + globalsup: 7, + haveGlobalMax: true, + globalinf: -Infinity, + }); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P4", + args: { x: 8, y: 3 }, + event: null, + }); + + await check_extrema({ + core, + maxima: [[5, 6]], + minima: [[8, 3]], + globalsup: Infinity, + globalinf: 0, + haveGlobalMin: true, + }); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P4", + args: { x: 8, y: 6 }, + event: null, + }); + + await check_extrema({ + core, + maxima: [ + [5, 6], + [7, 7], + ], + minima: [ + [6, 5], + [8, 6], + ], + globalsup: Infinity, + globalinf: 0, + haveGlobalMin: true, + }); + }); + + it("calculated extrema from spline, restrict to right-open domain", async () => { + let core = await createTestCore({ + doenetML: ` +

xmin = + xmax =

+ (0.7, 5.43) + (3,4) + (5,6) + (-5,6) + + `, + }); + + await check_extrema({ + core, + maxima: [ + [-2.15, 7], + [5, 6], + ], + minima: [[3, 4]], + globalsup: 7, + haveGlobalMax: true, + globalinf: 2, + }); + + await updateMathInputValue({ + latex: "-2", + componentName: "/xmin", + core, + }); + await updateMathInputValue({ + latex: "4", + componentName: "/xmax", + core, + }); + + await check_extrema({ + core, + maxima: [], + minima: [[3, 4]], + globalsup: 6.9918, + haveGlobalMax: true, + globalinf: 4, + haveGlobalMin: true, + }); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P1", + args: { x: 2, y: 2 }, + event: null, + }); + + await check_extrema({ + core, + maxima: [[-1.5, 7]], + minima: [[2, 2]], + globalsup: 7, + haveGlobalMax: true, + globalinf: 2, + haveGlobalMin: true, + }); + + await updateMathInputValue({ + latex: "-6", + componentName: "/xmin", + core, + }); + await updateMathInputValue({ + latex: "8", + componentName: "/xmax", + core, + }); + + await check_extrema({ + core, + maxima: [ + [-1.5, 7], + [5, 6], + ], + minima: [ + [-5, 6], + [2, 2], + ], + globalsup: 7, + haveGlobalMax: true, + globalinf: -3, + }); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P1", + args: { x: 3.6, y: 5.1 }, + event: null, + }); + + await check_extrema({ + core, + maxima: [ + [-1, 7], + [3.6, 5.1], + [5, 6], + ], + minima: [ + [-5, 6], + [3, 4], + [4.3, 5], + ], + globalsup: 7, + haveGlobalMax: true, + globalinf: -3, + }); + + await updateMathInputValue({ + latex: "-1", + componentName: "/xmin", + core, + }); + await updateMathInputValue({ + latex: "4", + componentName: "/xmax", + core, + }); + + await check_extrema({ + core, + maxima: [ + [-1, 7], + [3.6, 5.1], + ], + minima: [[3, 4]], + globalsup: 7, + haveGlobalMax: true, + globalinf: 4, + haveGlobalMin: true, + }); + }); + + it("calculated extrema from spline, restrict to left-open domain", async () => { + let core = await createTestCore({ + doenetML: ` +

xmin = + xmax =

+ (0.7, 5.43) + (3,4) + (5,6) + (-5,6) + + `, + }); + + await check_extrema({ + core, + maxima: [ + [-2.15, 7], + [5, 6], + ], + minima: [[3, 4]], + globalsup: 7, + haveGlobalMax: true, + globalinf: 2, + haveGlobalMin: true, + }); + + await updateMathInputValue({ + latex: "-2", + componentName: "/xmin", + core, + }); + await updateMathInputValue({ + latex: "4", + componentName: "/xmax", + core, + }); + + await check_extrema({ + core, + maxima: [], + minima: [[3, 4]], + globalsup: 6.9918, + globalinf: 4, + haveGlobalMin: true, + }); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P1", + args: { x: 2, y: 2 }, + event: null, + }); + + await check_extrema({ + core, + maxima: [[-1.5, 7]], + minima: [[2, 2]], + globalsup: 7, + haveGlobalMax: true, + globalinf: 2, + haveGlobalMin: true, + }); + + await updateMathInputValue({ + latex: "-6", + componentName: "/xmin", + core, + }); + await updateMathInputValue({ + latex: "8", + componentName: "/xmax", + core, + }); + + await check_extrema({ + core, + maxima: [ + [-1.5, 7], + [5, 6], + ], + minima: [ + [-5, 6], + [2, 2], + ], + globalsup: 7, + haveGlobalMax: true, + globalinf: -3, + haveGlobalMin: true, + }); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P1", + args: { x: 3.6, y: 5.1 }, + event: null, + }); + + await check_extrema({ + core, + maxima: [ + [-1, 7], + [3.6, 5.1], + [5, 6], + ], + minima: [ + [-5, 6], + [3, 4], + [4.3, 5], + ], + haveGlobalMax: true, + globalsup: 7, + globalinf: -3, + haveGlobalMin: true, + }); + + await updateMathInputValue({ + latex: "-1", + componentName: "/xmin", + core, + }); + await updateMathInputValue({ + latex: "4", + componentName: "/xmax", + core, + }); + + await check_extrema({ + core, + maxima: [[3.6, 5.1]], + minima: [[3, 4]], + globalsup: 7, + globalinf: 4, + haveGlobalMin: true, + }); + }); + + it("calculated extrema from spline, restrict domain, just through points", async () => { + let core = await createTestCore({ + doenetML: ` + (0, 0) + (2, -1.8) + (5,-4) + (7,0) + (8,1) + + `, + }); + + // it is set up so that minimum of quadratic interpolating between first two points + // is past maximum of domain + // check for bug where this stopped looking for minima + await check_extrema({ + core, + maxima: [], + minima: [[5, -4]], + globalsup: 2.3333, + globalinf: -4, + haveGlobalMin: true, + }); + + // now move points so that the minimum of the cubic interpolating between + // the first two points is past maximum of the domain + // check for bug where this stopped looking for minima + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P1", + args: { x: 0, y: -0.35 }, + event: null, + }); + await core.requestAction({ + actionName: "movePoint", + componentName: "/P2", + args: { x: 1.8, y: -1.36 }, + event: null, + }); + await core.requestAction({ + actionName: "movePoint", + componentName: "/P5", + args: { x: 1, y: -0.866 }, + event: null, + }); + + await check_extrema({ + core, + maxima: [], + minima: [[5, -4]], + globalsup: 12, + globalinf: -4, + haveGlobalMin: true, + }); + + // now move points so that maximum of quadratic interpolating between first two points + // is past maximum of domain + // check for bug where this stopped looking for maxima + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P1", + args: { x: 0, y: 0 }, + event: null, + }); + await core.requestAction({ + actionName: "movePoint", + componentName: "/P2", + args: { x: 2, y: 1.8 }, + event: null, + }); + await core.requestAction({ + actionName: "movePoint", + componentName: "/P3", + args: { x: 5, y: 4 }, + event: null, + }); + await core.requestAction({ + actionName: "movePoint", + componentName: "/P5", + args: { x: 8, y: -1 }, + event: null, + }); + + await check_extrema({ + core, + maxima: [[5, 4]], + minima: [], + globalsup: 4, + haveGlobalMax: true, + globalinf: -2.3333, + }); + + // now move points so that the maximum of the cubic interpolating between + // the first two points is past maximum of the domain + // check for bug where this stopped looking for maximum + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P1", + args: { x: 0, y: 0.35 }, + event: null, + }); + await core.requestAction({ + actionName: "movePoint", + componentName: "/P2", + args: { x: 1.8, y: 1.36 }, + event: null, + }); + await core.requestAction({ + actionName: "movePoint", + componentName: "/P5", + args: { x: 1, y: 0.866 }, + event: null, + }); + + await check_extrema({ + core, + maxima: [[5, 4]], + minima: [], + globalsup: 4, + haveGlobalMax: true, + globalinf: -12, + }); + }); + + it("calculated extrema from gaussians", async () => { + let core = await createTestCore({ + doenetML: ` + (0, 1) + (3, 1) + $P1.y exp(-(x-$P1.x)^2)+$P2.y exp(-(x-$P2.x)^2) + `, + }); + + await check_extrema({ + core, + maxima: [ + [0, 1], + [3, 1], + ], + minima: [[1.5, 0.21]], + globalsup: 1, + haveGlobalMax: true, + globalinf: 0, + haveGlobalMin: true, + }); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P2", + args: { x: 3, y: -1 }, + event: null, + }); + + await check_extrema({ + core, + maxima: [[0, 1]], + minima: [[3, -1]], + globalsup: 1, + haveGlobalMax: true, + globalinf: -1, + haveGlobalMin: true, + }); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P1", + args: { x: 0, y: -1 }, + event: null, + }); + + await check_extrema({ + core, + maxima: [[1.5, -0.21]], + minima: [ + [0, -1], + [3, -1], + ], + globalsup: 0, + haveGlobalMax: true, + globalinf: -1, + haveGlobalMin: true, + }); + }); + + it("calculated extrema from sinusoid", async () => { + let core = await createTestCore({ + doenetML: ` + Period: + sin(2*pi*x/$period) + `, + }); + + function calc_extrema(period) { + let numMaxima = 200 / period; + let maximumLocations = [...Array(numMaxima).keys()].map( + (x) => (x + 1 / 4 - numMaxima / 2) * period, + ); + let maxima = maximumLocations.map((x) => [x, 1]); + + let numMinima = 200 / period; + let minimumLocations = [...Array(numMinima).keys()].map( + (x) => (x + 3 / 4 - numMinima / 2) * period, + ); + let minima = minimumLocations.map((x) => [x, -1]); + + return { maxima, minima }; + } + + await check_extrema({ core, maxima: [], minima: [] }); + + let period = 10; + await updateMathInputValue({ + latex: `${period}`, + componentName: "/period", + core, + }); + + let extrema = calc_extrema(period); + + await check_extrema({ + core, + maxima: extrema.maxima, + minima: extrema.minima, + globalsup: 1, + haveGlobalMax: true, + globalinf: -1, + haveGlobalMin: true, + }); + + period = 5; + await updateMathInputValue({ + latex: `${period}`, + componentName: "/period", + core, + }); + + extrema = calc_extrema(period); + + await check_extrema({ + core, + maxima: extrema.maxima, + minima: extrema.minima, + haveGlobalMax: true, + globalsup: 1, + globalinf: -1, + haveGlobalMin: true, + }); + }); + + it("calculated extrema from sinusoid, restrict domain", async () => { + let core = await createTestCore({ + doenetML: ` + Period: + xmin = + xmax = + sin(2*pi*x/$period) + `, + }); + + function calc_extrema(period, minx, maxx) { + let numMaxima = Math.floor((maxx - minx) / period); + let firstMaxInd = Math.ceil(minx / period - 1 / 4); + + let maximumLocations = [...Array(numMaxima).keys()].map( + (x) => (x + 1 / 4 + firstMaxInd) * period, + ); + let maxima = maximumLocations.map((x) => [x, 1]); + + let numMinima = Math.floor((maxx - minx) / period); + let firstMinInd = Math.ceil(minx / period - 3 / 4); + + let minimumLocations = [...Array(numMinima).keys()].map( + (x) => (x + 3 / 4 + firstMinInd) * period, + ); + let minima = minimumLocations.map((x) => [x, -1]); + + return { maxima, minima }; + } + + let xmin = -10, + xmax = 10; + + await check_extrema({ core, maxima: [], minima: [] }); + + let period = 10; + await updateMathInputValue({ + latex: `${period}`, + componentName: "/period", + core, + }); + + let extrema = calc_extrema(period, xmin, xmax); + + await check_extrema({ + core, + maxima: extrema.maxima, + minima: extrema.minima, + globalsup: 1, + haveGlobalMax: true, + globalinf: -1, + haveGlobalMin: true, + }); + + xmin = -5; + xmax = 25; + await updateMathInputValue({ + latex: `${xmin}`, + componentName: "/xmin", + core, + }); + await updateMathInputValue({ + latex: `${xmax}`, + componentName: "/xmax", + core, + }); + + extrema = calc_extrema(period, xmin, xmax); + await check_extrema({ + core, + maxima: extrema.maxima, + minima: extrema.minima, + globalsup: 1, + haveGlobalMax: true, + globalinf: -1, + haveGlobalMin: true, + }); + + period = 5; + await updateMathInputValue({ + latex: `${period}`, + componentName: "/period", + core, + }); + + extrema = calc_extrema(period, xmin, xmax); + await check_extrema({ + core, + maxima: extrema.maxima, + minima: extrema.minima, + globalsup: 1, + haveGlobalMax: true, + globalinf: -1, + haveGlobalMin: true, + }); + + xmin = -1; + xmax = 9; + await updateMathInputValue({ + latex: `${xmin}`, + componentName: "/xmin", + core, + }); + await updateMathInputValue({ + latex: `${xmax}`, + componentName: "/xmax", + core, + }); + + extrema = calc_extrema(period, xmin, xmax); + await check_extrema({ + core, + maxima: extrema.maxima, + minima: extrema.minima, + globalsup: 1, + haveGlobalMax: true, + globalinf: -1, + haveGlobalMin: true, + }); + }); + + it("no extrema with horizontal asymptote", async () => { + let core = await createTestCore({ + doenetML: ` + + 1/(1+exp(-10*x)) + + `, + }); + + await check_extrema({ + core, + maxima: [], + minima: [], + globalsup: 1, + haveGlobalMax: true, + globalinf: 0, + haveGlobalMin: true, + }); + }); + + it("extrema of rational function", async () => { + let core = await createTestCore({ + doenetML: ` + + (x+8)(x-8)/((x-2)(x+4)(x-5)^2) + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + // values of extrema computed in Sage + let minimumLocations = [-2.29152990292159]; + let minima = minimumLocations.map((x) => [x, f(x)]); + let maximumLocations = [ + -11.6660173492088, 3.18454272065031, 9.77300453148004, + ]; + let maxima = maximumLocations.map((x) => [x, f(x)]); + + await check_extrema({ + core, + maxima, + minima, + globalsupLargerThan: 1e5, + haveGlobalMax: true, + globalinfSmallerThan: -1e5, + haveGlobalMin: true, + }); + }); + + it("intervals of extrema are not counted", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + `, + }); + + let f4 = await core.components!["/f4"].state.numericalf.value; + + await check_extrema({ + core, + maxima: [], + minima: [], + globalsup: Infinity, + globalinf: -Infinity, + globalsupLocation: -Infinity, + globalinfLocation: Infinity, + fName: "/f1", + }); + await check_extrema({ + core, + maxima: [], + minima: [], + globalsup: 5, + haveGlobalMax: true, + globalinf: 2, + haveGlobalMin: true, + globalsupLocation: -2, + globalinfLocation: -8, + fName: "/f2", + }); + await check_extrema({ + core, + maxima: [], + minima: [], + globalsup: 5, + haveGlobalMax: true, + globalinf: 2, + haveGlobalMin: true, + globalsupLocation: -2, + globalinfLocation: -7, + fName: "/f3", + }); + await check_extrema({ + core, + maxima: [], + minima: [], + globalsup: f4(-9, true), + globalinf: f4(14, true), + globalsupLocation: -9, + globalinfLocation: 14, + fName: "/f4", + }); + await check_extrema({ + core, + maxima: [], + minima: [], + globalsup: 5, + haveGlobalMax: true, + globalinf: 1, + haveGlobalMin: true, + globalsupLocation: -2, + globalinfLocation: 6, + fName: "/f5", + }); + await check_extrema({ + core, + maxima: [], + minima: [], + globalsup: 7, + haveGlobalMax: true, + globalinf: 2, + haveGlobalMin: true, + globalsupLocation: 6, + globalinfLocation: -8, + fName: "/f6", + }); + }); + + it("extrema of function with restricted domain, not explicit", async () => { + let core = await createTestCore({ + doenetML: ` + + log(x^2-1)*sqrt((x-5)^2-1) + + `, + }); + + let f = await core.components!["/f"].state.numericalf.value; + + let calculatedMinLocation = ( + await core.components!["/f"].state.globalMinimum.value + )[0]; + + await check_extrema({ + core, + maxima: [[2.614, 3.82]], + minima: [], + globalsup: f(-100), + globalinf: f(calculatedMinLocation), + haveGlobalMin: true, + globalsupLocation: -100, + globalinfLocation: -1, + }); + }); + + it("extrema in flat regions of functions", async () => { + let core = await createTestCore({ + doenetML: ` + 2-(x-1.0131)^10 + 3+(x+pi)^20 + -8+3/(1+exp(-100sin(3x))) + `, + }); + + let f1 = await core.components!["/f1"].state.numericalf.value; + let f2 = await core.components!["/f2"].state.numericalf.value; + + await check_extrema({ + core, + maxima: [[1.0131, 2]], + minima: [], + globalsup: 2, + haveGlobalMax: true, + globalinf: f1(-100), + globalsupLocation: 1.0131, + globalinfLocation: -100, + fName: "/f1", + }); + await check_extrema({ + core, + maxima: [], + minima: [[-Math.PI, 3]], + globalsup: f2(100), + globalinf: 3, + haveGlobalMin: true, + globalsupLocation: 100, + globalinfLocation: -Math.PI, + fName: "/f2", + }); + await check_extrema({ + core, + maxima: [ + [(5 * Math.PI) / 6, -5], + [(9 * Math.PI) / 6, -5], + ], + minima: [ + [(3 * Math.PI) / 6, -8], + [(7 * Math.PI) / 6, -8], + ], + globalsup: -5, + haveGlobalMax: true, + globalinf: -8, + haveGlobalMin: true, + globalsupLocation: (5 * Math.PI) / 6, + globalinfLocation: (3 * Math.PI) / 6, + fName: "/f3", + }); + }); + + it("global extrema, in flat regions too flat for local extrema", async () => { + let core = await createTestCore({ + doenetML: ` + 2-(x-1.0131)^100 + 3+(x+pi)^200 + -8+3/(1+exp(-1000sin(3x))) + `, + }); + + let f1 = await core.components!["/f1"].state.numericalf.value; + + await check_extrema({ + core, + maxima: [], + minima: [], + globalsup: 2, + haveGlobalMax: true, + globalinf: f1(-100), + globalinfLocation: -100, + fName: "/f1", + }); + expect(core.components!["/f1"].stateValues.globalMaximum[0]).within( + 0.0131, + 2.0131, + ); + + await check_extrema({ + core, + maxima: [], + minima: [], + globalsup: Infinity, + globalinf: 3, + haveGlobalMin: true, + fName: "/f2", + }); + expect(core.components!["/f2"].stateValues.globalMinimum[0]).within( + -Math.PI - 1, + -Math.PI + 1, + ); + await check_extrema({ + core, + maxima: [], + minima: [], + globalsup: -5, + haveGlobalMax: true, + globalinf: -8, + haveGlobalMin: true, + fName: "/f3", + }); + expect(core.components!["/f3"].stateValues.globalMaximum[0]).within( + 1, + Math.PI / 3, + ); + expect(core.components!["/f3"].stateValues.globalMinimum[0]).within( + Math.PI / 3, + (2 * Math.PI) / 3, + ); + }); + + it("extrema at domain endpoints, function from formula", async () => { + let core = await createTestCore({ + doenetML: ` + cos(x) + cos(x)+1 + sin(x)+2 + sin(x)+3 + + cos(x) + sin(x)+2 + sin(x)+3 + + cos(x) + cos(x)+1 + cos(x-pi)+4 + cos(x-pi)+5 + + cos(x) + cos(x)+1 + cos(x-pi)+4 + cos(x-pi)+5 + `, + }); + + await check_extrema({ + core, + maxima: [[0, 1]], + minima: [[Math.PI, -1]], + globalsup: 1, + haveGlobalMax: true, + globalinf: -1, + haveGlobalMin: true, + fName: "/f1", + }); + + await check_extrema({ + core, + maxima: [ + [0, 2], + [2 * Math.PI, 2], + ], + minima: [ + [-Math.PI, 0], + [Math.PI, 0], + ], + globalsup: 2, + haveGlobalMax: true, + globalinf: 0, + haveGlobalMin: true, + fName: "/f2", + }); + + await check_extrema({ + core, + maxima: [[0.5 * Math.PI, 3]], + minima: [ + [-0.5 * Math.PI, 1], + [1.5 * Math.PI, 1], + ], + globalsup: 3, + haveGlobalMax: true, + globalinf: 1, + haveGlobalMin: true, + fName: "/f3", + }); + + await check_extrema({ + core, + maxima: [ + [-1.5 * Math.PI, 4], + [0.5 * Math.PI, 4], + ], + minima: [[-0.5 * Math.PI, 2]], + globalsup: 4, + haveGlobalMax: true, + globalinf: 2, + haveGlobalMin: true, + fName: "/f4", + }); + + await check_extrema({ + core, + maxima: [[0, 1]], + minima: [[Math.PI, -1]], + globalsup: 1, + haveGlobalMax: true, + globalinf: -1, + haveGlobalMin: true, + fName: "/f1a", + }); + + await check_extrema({ + core, + maxima: [[0.5 * Math.PI, 3]], + minima: [ + [-0.5 * Math.PI, 1], + [1.5 * Math.PI, 1], + ], + globalsup: 3, + haveGlobalMax: true, + globalinf: 1, + haveGlobalMin: true, + fName: "/f3a", + }); + + await check_extrema({ + core, + maxima: [ + [-1.5 * Math.PI, 4], + [0.5 * Math.PI, 4], + ], + minima: [[-0.5 * Math.PI, 2]], + globalsup: 4, + haveGlobalMax: true, + globalinf: 2, + haveGlobalMin: true, + fName: "/f4a", + }); + + await check_extrema({ + core, + maxima: [[2 * Math.PI, 1]], + minima: [[Math.PI, -1]], + globalsup: 1, + haveGlobalMax: true, + globalinf: -1, + haveGlobalMin: true, + fName: "/f5", + }); + + await check_extrema({ + core, + maxima: [ + [0, 2], + [2 * Math.PI, 2], + ], + minima: [ + [Math.PI, 0], + [3 * Math.PI, 0], + ], + globalsup: 2, + haveGlobalMax: true, + globalinf: 0, + haveGlobalMin: true, + fName: "/f6", + }); + + await check_extrema({ + core, + maxima: [ + [Math.PI, 5], + [3 * Math.PI, 5], + ], + minima: [[2 * Math.PI, 3]], + globalsup: 5, + haveGlobalMax: true, + globalinf: 3, + haveGlobalMin: true, + fName: "/f7", + }); + + await check_extrema({ + core, + maxima: [[Math.PI, 6]], + minima: [ + [0, 4], + [2 * Math.PI, 4], + ], + globalsup: 6, + haveGlobalMax: true, + globalinf: 4, + haveGlobalMin: true, + fName: "/f8", + }); + + await check_extrema({ + core, + maxima: [[-2 * Math.PI, 1]], + minima: [[-Math.PI, -1]], + globalsup: 1, + haveGlobalMax: true, + globalinf: -1, + haveGlobalMin: true, + fName: "/f9", + }); + + await check_extrema({ + core, + maxima: [ + [-2 * Math.PI, 2], + [0, 2], + ], + minima: [ + [-3 * Math.PI, 0], + [-1 * Math.PI, 0], + ], + globalsup: 2, + haveGlobalMax: true, + globalinf: 0, + haveGlobalMin: true, + fName: "/f10", + }); + + await check_extrema({ + core, + maxima: [[-Math.PI, 5]], + minima: [ + [-2 * Math.PI, 3], + [0, 3], + ], + globalsup: 5, + haveGlobalMax: true, + globalinf: 3, + haveGlobalMin: true, + fName: "/f11", + }); + + await check_extrema({ + core, + maxima: [ + [-3 * Math.PI, 6], + [-1 * Math.PI, 6], + ], + minima: [[-2 * Math.PI, 4]], + globalsup: 6, + haveGlobalMax: true, + globalinf: 4, + haveGlobalMin: true, + fName: "/f12", + }); + }); + + it("extrema at domain endpoints, function from formula, link=false", async () => { + // Note: checking to see if rounding attributes are properly copied + // for wrapped array state variables when link="false" + let core = await createTestCore({ + doenetML: ` + cos(x) + cos(x)+1 + + $f1.extrema{assignNames="f1e1 f1e2" link="false"} + $f2.extrema{assignNames="f2e1 f2e2 f2e3 f2e4" link="false"} + + + `, + }); + + const stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/f1e1"].stateValues.latex)).eq( + "(0,1)", + ); + expect(cleanLatex(stateVariables["/f1e2"].stateValues.latex)).eq( + `(${Math.round(Math.PI * 10 ** 5) / 10 ** 5},-1)`, + ); + expect(cleanLatex(stateVariables["/f2e1"].stateValues.latex)).eq( + `(${Math.round(-Math.PI * 10 ** 5) / 10 ** 5},0)`, + ); + expect(cleanLatex(stateVariables["/f2e2"].stateValues.latex)).eq( + "(0,2)", + ); + expect(cleanLatex(stateVariables["/f2e3"].stateValues.latex)).eq( + `(${Math.round(Math.PI * 10 ** 5) / 10 ** 5},0)`, + ); + }); + + it("extrema at domain endpoints, interpolated function", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + + + + `, + }); + + let extremax1 = [0, 1 / 3, 2 / 3, 1].map( + (a) => -Math.sqrt(2) * (1 - a) + Math.sqrt(10) * a, + ); + let extremax2 = [0, 1 / 3, 2 / 3, 1].map((a) => Math.sqrt(10) * a); + let extremax3 = [0, 1 / 3, 2 / 3, 1].map( + (a) => -Math.sqrt(2) * (1 - a), + ); + + await check_extrema({ + core, + maxima: [[extremax1[2], Math.sqrt(11) + 1]], + minima: [[extremax1[1], Math.sqrt(3) - 1]], + globalsup: Math.sqrt(11) + 1, + haveGlobalMax: true, + globalinf: Math.sqrt(3) - 1, + haveGlobalMin: true, + fName: "/f1", + }); + await check_extrema({ + core, + maxima: [ + [extremax1[0], Math.sqrt(3) + 1], + [extremax1[2], Math.sqrt(11) + 2], + ], + minima: [ + [extremax1[1], Math.sqrt(3)], + [extremax1[3], Math.sqrt(11) + 1], + ], + globalsup: Math.sqrt(11) + 2, + haveGlobalMax: true, + globalinf: Math.sqrt(3), + haveGlobalMin: true, + fName: "/f2", + }); + await check_extrema({ + core, + maxima: [[extremax1[2], Math.sqrt(11) + 3]], + minima: [[extremax1[1], Math.sqrt(3) + 1]], + globalsup: Math.sqrt(11) + 3, + haveGlobalMax: true, + globalinf: Math.sqrt(3) + 1, + haveGlobalMin: true, + fName: "/f3", + }); + await check_extrema({ + core, + maxima: [[extremax2[2], Math.sqrt(11) + 1]], + minima: [[extremax2[1], Math.sqrt(3) - 1]], + globalsup: Math.sqrt(11) + 1, + haveGlobalMax: true, + globalinf: Math.sqrt(3) - 1, + haveGlobalMin: true, + fName: "/f4", + }); + await check_extrema({ + core, + maxima: [ + [extremax2[0], Math.sqrt(3) + 1], + [extremax2[2], Math.sqrt(11) + 2], + ], + minima: [ + [extremax2[1], Math.sqrt(3)], + [extremax2[3], Math.sqrt(11) + 1], + ], + globalsup: Math.sqrt(11) + 2, + haveGlobalMax: true, + globalinf: Math.sqrt(3), + haveGlobalMin: true, + fName: "/f5", + }); + await check_extrema({ + core, + maxima: [[extremax2[2], Math.sqrt(11) + 3]], + minima: [[extremax2[1], Math.sqrt(3) + 1]], + globalsup: Math.sqrt(11) + 3, + haveGlobalMax: true, + globalinf: Math.sqrt(3) + 1, + haveGlobalMin: true, + fName: "/f6", + }); + await check_extrema({ + core, + maxima: [[extremax3[2], Math.sqrt(11) + 1]], + minima: [[extremax3[1], Math.sqrt(3) - 1]], + globalsup: Math.sqrt(11) + 1, + haveGlobalMax: true, + globalinf: Math.sqrt(3) - 1, + haveGlobalMin: true, + fName: "/f7", + }); + await check_extrema({ + core, + maxima: [ + [extremax3[0], Math.sqrt(3) + 1], + [extremax3[2], Math.sqrt(11) + 2], + ], + minima: [ + [extremax3[1], Math.sqrt(3)], + [extremax3[3], Math.sqrt(11) + 1], + ], + globalsup: Math.sqrt(11) + 2, + haveGlobalMax: true, + globalinf: Math.sqrt(3), + haveGlobalMin: true, + fName: "/f8", + }); + await check_extrema({ + core, + maxima: [[extremax3[2], Math.sqrt(11) + 3]], + minima: [[extremax3[1], Math.sqrt(3) + 1]], + globalsup: Math.sqrt(11) + 3, + haveGlobalMax: true, + globalinf: Math.sqrt(3) + 1, + haveGlobalMin: true, + fName: "/f9", + }); + }); + + it("two functions with mutual dependence", async () => { + let core = await createTestCore({ + doenetML: ` + (1,2) + (3,4) + (-5,7) + (8,-1) + + + + `, + }); + + async function check_items({ + numMaxf2, + numMinf2, + maxf1, + }: { + numMaxf2: number; + numMinf2: number; + maxf1: number[]; + }) { + const stateVariables = await returnAllStateVariables(core); + + let f1 = stateVariables["/f1"].stateValues; + let f2 = stateVariables["/f2"].stateValues; + + expect(f1.numMaxima).eq(1); + expect(f1.numMinima).eq(2); + expect(f2.numMaxima).eq(numMaxf2); + expect(f2.numMinima).eq(numMinf2); + + expect(f1.maxima[0][0]).eq(maxf1[0]); + expect(f1.maxima[0][1]).eq(maxf1[1]); + + expect(f1.xscale).eq(1); + expect(f1.yscale).eq(5); + expect(f2.xscale).eq(1); + expect(f2.yscale).eq(5); + } + + await check_items({ numMaxf2: 2, numMinf2: 1, maxf1: [2, 1] }); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P1", + args: { x: 2, y: 6 }, + event: null, + }); + + await check_items({ numMaxf2: 1, numMinf2: 0, maxf1: [1, 0] }); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P2", + args: { x: 3, y: 7 }, + event: null, + }); + await core.requestAction({ + actionName: "movePoint", + componentName: "/P3", + args: { x: 9, y: 0 }, + event: null, + }); + + await check_items({ numMaxf2: 2, numMinf2: 2, maxf1: [2, 2] }); + }); + + it("shadowed works correctly with initially unresolved", async () => { + let core = await createTestCore({ + doenetML: ` + + + + $mi2 x^3+1 + + $f1{name="f1a"} + +

$f1a.xscale

+

$f1.xscale

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p1"].stateValues.text).eq("NaN"); + expect(stateVariables["/p2"].stateValues.text).eq("NaN"); + + expect(cleanLatex(stateVariables["/f1"].stateValues.latex)).eq( + "_x^{3}+1", + ); + + await updateMathInputValue({ latex: "1", componentName: "/mi1", core }); + await updateMathInputValue({ latex: "2", componentName: "/mi2", core }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p1"].stateValues.text).eq("1"); + expect(stateVariables["/p2"].stateValues.text).eq("1"); + + expect(cleanLatex(stateVariables["/f1"].stateValues.latex)).eq( + "2x^{3}+1", + ); + + let f = stateVariables["/f1"].stateValues.numericalf; + expect(f(-2)).eq(2 * (-2) ** 3 + 1); + let fa = stateVariables["/f1a"].stateValues.numericalf; + expect(fa(-2)).eq(2 * (-2) ** 3 + 1); + + await updateMathInputValue({ latex: "3", componentName: "/mi1", core }); + await updateMathInputValue({ latex: "4", componentName: "/mi2", core }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p1"].stateValues.text).eq("3"); + expect(stateVariables["/p2"].stateValues.text).eq("3"); + + expect(cleanLatex(stateVariables["/f1"].stateValues.latex)).eq( + "4x^{3}+1", + ); + + f = stateVariables["/f1"].stateValues.numericalf; + expect(f(-2)).eq(4 * (-2) ** 3 + 1); + fa = stateVariables["/f1a"].stateValues.numericalf; + expect(fa(-2)).eq(4 * (-2) ** 3 + 1); + }); + + it("extrema of quartic, copied multiple times", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + $mi1 x^4 + $mi2 x^3 +$mi3 x^2 +1 + + $f1{name="f1a"} + + $f1a{name="f1b"} + `, + }); + + let maxima = [[0, 1]]; + let minima = [ + [-1, 0], + [1, 0], + ]; + + await check_extrema({ + core, + maxima, + minima, + globalinf: minima[0][1], + haveGlobalMin: true, + globalsupLargerThan: 1e6, + fName: "/f1", + }); + + await check_extrema({ + core, + maxima, + minima, + globalinf: minima[0][1], + haveGlobalMin: true, + globalsupLargerThan: 1e6, + fName: "/f1a", + }); + + await check_extrema({ + core, + maxima, + minima, + globalinf: minima[0][1], + haveGlobalMin: true, + globalsupLargerThan: 1e6, + fName: "/f1b", + }); + + await updateMathInputValue({ latex: "2", componentName: "/mi2", core }); + + maxima = [[0, 1]]; + minima = [ + [-2, -7], + [0.5, 13 / 16], + ]; + + await check_extrema({ + core, + maxima, + minima, + globalinf: minima[0][1], + haveGlobalMin: true, + globalsupLargerThan: 1e6, + fName: "/f1", + }); + + await check_extrema({ + core, + maxima, + minima, + globalinf: minima[0][1], + haveGlobalMin: true, + globalsupLargerThan: 1e6, + fName: "/f1a", + }); + + await check_extrema({ + core, + maxima, + minima, + globalinf: minima[0][1], + haveGlobalMin: true, + globalsupLargerThan: 1e6, + fName: "/f1b", + }); + + await updateMathInputValue({ + latex: "-1", + componentName: "/mi1", + core, + }); + + maxima = [[0, 1]]; + minima = []; + + await check_extrema({ + core, + maxima, + minima, + globalsup: maxima[0][1], + haveGlobalMax: true, + globalinfSmallerThan: -1e6, + fName: "/f1", + }); + await check_extrema({ + core, + maxima, + minima, + globalsup: maxima[0][1], + haveGlobalMax: true, + globalinfSmallerThan: -1e6, + fName: "/f1a", + }); + await check_extrema({ + core, + maxima, + minima, + globalsup: maxima[0][1], + haveGlobalMax: true, + globalinfSmallerThan: -1e6, + fName: "/f1b", + }); + }); + + it("function of function formula can redefine variable", async () => { + let core = await createTestCore({ + doenetML: ` + st^3 + + $f + $f.formula + + $f{name="f4"} + $f2{name="f5"} + $f3{name="f6"} + +

$$f(u)

+

$$f2(u)

+

$$f3(u)

+

$$f4(u)

+

$$f5(u)

+

$$f6(u)

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/f"].stateValues.variables[0].tree).eq("t"); + expect(stateVariables["/f2"].stateValues.variables[0].tree).eq("t"); + expect(stateVariables["/f3"].stateValues.variables[0].tree).eq("s"); + expect(stateVariables["/f4"].stateValues.variables[0].tree).eq("t"); + expect(stateVariables["/f5"].stateValues.variables[0].tree).eq("t"); + expect(stateVariables["/f6"].stateValues.variables[0].tree).eq("s"); + + expect(stateVariables["/f"].stateValues.formula.tree).eqls([ + "*", + "s", + ["^", "t", 3], + ]); + expect(stateVariables["/f2"].stateValues.formula.tree).eqls([ + "*", + "s", + ["^", "t", 3], + ]); + expect(stateVariables["/f3"].stateValues.formula.tree).eqls([ + "*", + "s", + ["^", "t", 3], + ]); + expect(stateVariables["/f4"].stateValues.formula.tree).eqls([ + "*", + "s", + ["^", "t", 3], + ]); + expect(stateVariables["/f5"].stateValues.formula.tree).eqls([ + "*", + "s", + ["^", "t", 3], + ]); + expect(stateVariables["/f6"].stateValues.formula.tree).eqls([ + "*", + "s", + ["^", "t", 3], + ]); + + expect( + stateVariables[ + stateVariables["/fOfu"].activeChildren[0].componentName + ].stateValues.value.tree, + ).eqls(["*", "s", ["^", "u", 3]]); + expect( + stateVariables[ + stateVariables["/f2Ofu"].activeChildren[0].componentName + ].stateValues.value.tree, + ).eqls(["*", "s", ["^", "u", 3]]); + expect( + stateVariables[ + stateVariables["/f3Ofu"].activeChildren[0].componentName + ].stateValues.value.tree, + ).eqls(["*", "u", ["^", "t", 3]]); + expect( + stateVariables[ + stateVariables["/f4Ofu"].activeChildren[0].componentName + ].stateValues.value.tree, + ).eqls(["*", "s", ["^", "u", 3]]); + expect( + stateVariables[ + stateVariables["/f5Ofu"].activeChildren[0].componentName + ].stateValues.value.tree, + ).eqls(["*", "s", ["^", "u", 3]]); + expect( + stateVariables[ + stateVariables["/f6Ofu"].activeChildren[0].componentName + ].stateValues.value.tree, + ).eqls(["*", "u", ["^", "t", 3]]); + }); + + it("function of interpolated function can redefine variable without changing function", async () => { + let core = await createTestCore({ + doenetML: ` + + + $f + $f + + $f{name="f4"} + $f2{name="f5"} + $f3{name="f6"} + + $f.variable{assignNames="fv"} + $f2.variable{assignNames="f2v"} + $f3.variable{assignNames="f3v"} + $f4.variable{assignNames="f4v"} + $f5.variable{assignNames="f5v"} + $f6.variable{assignNames="f6v"} + +

$$f(0)

+

$$f2(0)

+

$$f3(0)

+

$$f4(0)

+

$$f5(0)

+

$$f6(0)

+ +

$$f(1)

+

$$f2(1)

+

$$f3(1)

+

$$f4(1)

+

$$f5(1)

+

$$f6(1)

+ +

$$f(2)

+

$$f2(2)

+

$$f3(2)

+

$$f4(2)

+

$$f5(2)

+

$$f6(2)

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/f"].stateValues.variables[0].tree).eq("x"); + expect(stateVariables["/f2"].stateValues.variables[0].tree).eq("x"); + expect(stateVariables["/f3"].stateValues.variables[0].tree).eq("s"); + expect(stateVariables["/f4"].stateValues.variables[0].tree).eq("x"); + expect(stateVariables["/f5"].stateValues.variables[0].tree).eq("x"); + expect(stateVariables["/f6"].stateValues.variables[0].tree).eq("s"); + + let Of0names = [ + "/fOf0", + "/f2Of0", + "/f3Of0", + "/f4Of0", + "/f5Of0", + "/f6Of0", + ]; + + for (let name of Of0names) { + expect( + stateVariables[ + stateVariables[name].activeChildren[0].componentName + ].stateValues.value.tree, + ).eqls(2); + } + + let Of1names = [ + "/fOf1", + "/f2Of1", + "/f3Of1", + "/f4Of1", + "/f5Of1", + "/f6Of1", + ]; + + for (let name of Of1names) { + expect( + stateVariables[ + stateVariables[name].activeChildren[0].componentName + ].stateValues.value.tree, + ).eqls(3); + } + + let Of2names = [ + "/fOf2", + "/f2Of2", + "/f3Of2", + "/f4Of2", + "/f5Of2", + "/f6Of2", + ]; + + for (let name of Of2names) { + expect( + stateVariables[ + stateVariables[name].activeChildren[0].componentName + ].stateValues.value.tree, + ).eqls(6); + } + }); + + it("extrema not resolved if not requested", async () => { + let core = await createTestCore({ + doenetML: ` + sin(x) + $f{name="f2"} + $f + + $g{name="g2"} + $g + `, + }); + + let stateVariables = core.components!; + + expect(stateVariables["/f"].state.formula.isResolved).eq(true); + expect(stateVariables["/f"].state.symbolicfs.isResolved).eq(false); + expect(stateVariables["/f"].state.numericalfs.isResolved).eq(false); + expect(stateVariables["/f"].state.allMaxima.isResolved).eq(false); + expect(stateVariables["/f"].state.allMinima.isResolved).eq(false); + expect(stateVariables["/f"].state.allExtrema.isResolved).eq(false); + expect(stateVariables["/f"].state.numMaxima.isResolved).eq(false); + expect(stateVariables["/f"].state.numMinima.isResolved).eq(false); + expect(stateVariables["/f"].state.numExtrema.isResolved).eq(false); + expect(stateVariables["/f"].state.maxima.isResolved).eq(false); + expect(stateVariables["/f"].state.minima.isResolved).eq(false); + expect(stateVariables["/f"].state.extrema.isResolved).eq(false); + + expect(stateVariables["/f2"].state.formula.isResolved).eq(true); + expect(stateVariables["/f2"].state.symbolicfs.isResolved).eq(false); + expect(stateVariables["/f2"].state.numericalfs.isResolved).eq(false); + expect(stateVariables["/f2"].state.allMaxima.isResolved).eq(false); + expect(stateVariables["/f2"].state.allMinima.isResolved).eq(false); + expect(stateVariables["/f2"].state.allExtrema.isResolved).eq(false); + expect(stateVariables["/f2"].state.numMaxima.isResolved).eq(false); + expect(stateVariables["/f2"].state.numMinima.isResolved).eq(false); + expect(stateVariables["/f2"].state.numExtrema.isResolved).eq(false); + expect(stateVariables["/f2"].state.maxima.isResolved).eq(false); + expect(stateVariables["/f2"].state.minima.isResolved).eq(false); + expect(stateVariables["/f2"].state.extrema.isResolved).eq(false); + + expect(stateVariables["/f3"].state.formula.isResolved).eq(true); + expect(stateVariables["/f3"].state.symbolicfs.isResolved).eq(false); + expect(stateVariables["/f3"].state.numericalfs.isResolved).eq(false); + expect(stateVariables["/f3"].state.allMaxima.isResolved).eq(false); + expect(stateVariables["/f3"].state.allMinima.isResolved).eq(false); + expect(stateVariables["/f3"].state.allExtrema.isResolved).eq(false); + expect(stateVariables["/f3"].state.numMaxima.isResolved).eq(false); + expect(stateVariables["/f3"].state.numMinima.isResolved).eq(false); + expect(stateVariables["/f3"].state.numExtrema.isResolved).eq(false); + expect(stateVariables["/f3"].state.maxima.isResolved).eq(false); + expect(stateVariables["/f3"].state.minima.isResolved).eq(false); + expect(stateVariables["/f3"].state.extrema.isResolved).eq(false); + + expect(stateVariables["/g"].state.formula.isResolved).eq(true); + expect(stateVariables["/g"].state.symbolicfs.isResolved).eq(false); + expect(stateVariables["/g"].state.numericalfs.isResolved).eq(false); + expect(stateVariables["/g"].state.allMaxima.isResolved).eq(false); + expect(stateVariables["/g"].state.allMinima.isResolved).eq(false); + expect(stateVariables["/g"].state.allExtrema.isResolved).eq(false); + expect(stateVariables["/g"].state.numMaxima.isResolved).eq(false); + expect(stateVariables["/g"].state.numMinima.isResolved).eq(false); + expect(stateVariables["/g"].state.numExtrema.isResolved).eq(false); + expect(stateVariables["/g"].state.maxima.isResolved).eq(false); + expect(stateVariables["/g"].state.minima.isResolved).eq(false); + expect(stateVariables["/g"].state.extrema.isResolved).eq(false); + + expect(stateVariables["/g2"].state.formula.isResolved).eq(true); + expect(stateVariables["/g2"].state.symbolicfs.isResolved).eq(false); + expect(stateVariables["/g2"].state.numericalfs.isResolved).eq(false); + expect(stateVariables["/g2"].state.allMaxima.isResolved).eq(false); + expect(stateVariables["/g2"].state.allMinima.isResolved).eq(false); + expect(stateVariables["/g2"].state.allExtrema.isResolved).eq(false); + expect(stateVariables["/g2"].state.numMaxima.isResolved).eq(false); + expect(stateVariables["/g2"].state.numMinima.isResolved).eq(false); + expect(stateVariables["/g2"].state.numExtrema.isResolved).eq(false); + expect(stateVariables["/g2"].state.maxima.isResolved).eq(false); + expect(stateVariables["/g2"].state.minima.isResolved).eq(false); + expect(stateVariables["/g2"].state.extrema.isResolved).eq(false); + + expect(stateVariables["/g3"].state.formula.isResolved).eq(true); + expect(stateVariables["/g3"].state.symbolicfs.isResolved).eq(false); + expect(stateVariables["/g3"].state.numericalfs.isResolved).eq(false); + expect(stateVariables["/g3"].state.allMaxima.isResolved).eq(false); + expect(stateVariables["/g3"].state.allMinima.isResolved).eq(false); + expect(stateVariables["/g3"].state.allExtrema.isResolved).eq(false); + expect(stateVariables["/g3"].state.numMaxima.isResolved).eq(false); + expect(stateVariables["/g3"].state.numMinima.isResolved).eq(false); + expect(stateVariables["/g3"].state.numExtrema.isResolved).eq(false); + expect(stateVariables["/g3"].state.maxima.isResolved).eq(false); + expect(stateVariables["/g3"].state.minima.isResolved).eq(false); + expect(stateVariables["/g3"].state.extrema.isResolved).eq(false); + }); + + it("function determined by formula, specify 1 input", async () => { + let core = await createTestCore({ + doenetML: ` + 3/(1+e^(-x/2)) + + `, + }); + + await test_function_3_over_exp(core); + }); + + async function test_function_two_var_exp(core) { + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/f"].stateValues.numInputs).eq(2); + + expect(stateVariables["/f"].stateValues.domain.map((x) => x.tree)).eqls( + [ + [ + "interval", + ["tuple", -Infinity, Infinity], + ["tuple", false, false], + ], + [ + "interval", + ["tuple", -Infinity, Infinity], + ["tuple", false, false], + ], + ], + ); + + const f = stateVariables["/f"].stateValues.numericalf; + + expect(f(-5, 7)).closeTo(3 / (7 + Math.exp(5 / 2)), 1e-12); + expect(f(1, 4)).closeTo(3 / (4 + Math.exp(-1 / 2)), 1e-12); + } + + it("function of two variables determined by formula", async () => { + let core = await createTestCore({ + doenetML: ` + 3/(y+e^(-x/2)) + `, + }); + + await test_function_two_var_exp(core); + }); + + it("function of two variables determined by formula, specify variables", async () => { + let core = await createTestCore({ + doenetML: ` + 3/(r+e^(-q/2)) + `, + }); + + await test_function_two_var_exp(core); + }); + + it("function of two variables determined by formula, specify variables, no numInputs specified", async () => { + let core = await createTestCore({ + doenetML: ` + 3/(r+e^(-q/2)) + `, + }); + + await test_function_two_var_exp(core); + }); + + it("function of two variables determined by formula, specify variables, no numInputs specified, restrict domain", async () => { + let core = await createTestCore({ + doenetML: ` + 3/(r+e^(-q/2)) + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/f"].stateValues.numInputs).eq(2); + expect(stateVariables["/f"].stateValues.domain.map((x) => x.tree)).eqls( + [ + ["interval", ["tuple", -4, 2], ["tuple", false, true]], + ["interval", ["tuple", 1, 3], ["tuple", true, false]], + ], + ); + + const f = stateVariables["/f"].stateValues.numericalf; + + expect(f(-4, 2)).eqls(NaN); + expect(f(3, 3)).eqls(NaN); + expect(f(2, 1)).closeTo(3 / (1 + Math.exp(-1)), 1e-12); + expect(f(-3, 2)).closeTo(3 / (2 + Math.exp(3 / 2)), 1e-12); + }); + + async function test_function_three_var_exp(core) { + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/f"].stateValues.numInputs).eq(3); + expect(stateVariables["/f"].stateValues.domain.map((x) => x.tree)).eqls( + [ + [ + "interval", + ["tuple", -Infinity, Infinity], + ["tuple", false, false], + ], + [ + "interval", + ["tuple", -Infinity, Infinity], + ["tuple", false, false], + ], + [ + "interval", + ["tuple", -Infinity, Infinity], + ["tuple", false, false], + ], + ], + ); + + const f = stateVariables["/f"].stateValues.numericalf; + + expect(f(-5, 7, -2)).closeTo(-2 / (7 + Math.exp(5 / 2)), 1e-12); + expect(f(1, 4, -9)).closeTo(-9 / (4 + Math.exp(-1 / 2)), 1e-12); + } + + it("function of three variables determined by formula", async () => { + let core = await createTestCore({ + doenetML: ` + z/(y+e^(-x/2)) + `, + }); + + await test_function_three_var_exp(core); + }); + + it("function of three variables determined by formula, specify variables", async () => { + let core = await createTestCore({ + doenetML: ` + s/(r+e^(-q/2)) + `, + }); + + await test_function_three_var_exp(core); + }); + + it("function of three variables determined by formula, specify variables, restrict domain", async () => { + let core = await createTestCore({ + doenetML: ` + s/(r+e^(-q/2)) + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/f"].stateValues.numInputs).eq(3); + expect(stateVariables["/f"].stateValues.domain.map((x) => x.tree)).eqls( + [ + ["interval", ["tuple", 2, 5], ["tuple", false, false]], + ["interval", ["tuple", -4, 4], ["tuple", true, true]], + ["interval", ["tuple", -3, -1], ["tuple", true, false]], + ], + ); + + const f = stateVariables["/f"].stateValues.numericalf; + + expect(f(5, 3, -3)).eqls(NaN); + expect(f(4, 3, -3)).closeTo(-3 / (3 + Math.exp(-2)), 1e-12); + expect(f(3, 2, -1)).eqls(NaN); + expect(f(3, 2, -2)).closeTo(-2 / (2 + Math.exp(-3 / 2)), 1e-12); + }); + + async function test_function_four_var_exp(core) { + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/f"].stateValues.numInputs).eq(4); + expect(stateVariables["/f"].stateValues.domain.map((x) => x.tree)).eqls( + [ + [ + "interval", + ["tuple", -Infinity, Infinity], + ["tuple", false, false], + ], + [ + "interval", + ["tuple", -Infinity, Infinity], + ["tuple", false, false], + ], + [ + "interval", + ["tuple", -Infinity, Infinity], + ["tuple", false, false], + ], + [ + "interval", + ["tuple", -Infinity, Infinity], + ["tuple", false, false], + ], + ], + ); + + const f = stateVariables["/f"].stateValues.numericalf; + + expect(f(-5, 7, -2, 6)).closeTo(-2 / (7 + Math.exp(5 / 2)) + 6, 1e-12); + expect(f(1, 4, -9, -8)).closeTo(-9 / (4 + Math.exp(-1 / 2)) - 8, 1e-12); + } + + it("function of four variables determined by formula", async () => { + let core = await createTestCore({ + doenetML: ` + x_3/(x_2+e^(-x_1/2))+x_4 + `, + }); + + await test_function_four_var_exp(core); + }); + + it("function of four variables determined by formula, specify some variables", async () => { + let core = await createTestCore({ + doenetML: ` + z/(y+e^(-x/2))+x_4 + `, + }); + + await test_function_four_var_exp(core); + }); + + it("function of four variables determined by formula, specify some variables, restrict domain", async () => { + let core = await createTestCore({ + doenetML: ` + z/(y+e^(-x/2))+x_4 + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/f"].stateValues.numInputs).eq(4); + expect(stateVariables["/f"].stateValues.domain.map((x) => x.tree)).eqls( + [ + ["interval", ["tuple", -5, 1], ["tuple", true, true]], + ["interval", ["tuple", 2, 4], ["tuple", true, false]], + ["interval", ["tuple", 4, 7], ["tuple", false, true]], + ["interval", ["tuple", -8, -4], ["tuple", false, false]], + ], + ); + + const f = stateVariables["/f"].stateValues.numericalf; + + expect(f(-5, 2, 7, -4)).eqls(NaN); + expect(f(-5, 2, 7, -5)).closeTo(7 / (2 + Math.exp(5 / 2)) - 5, 1e-12); + }); + + async function test_2d_vector_function_single_var(core) { + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/f"].stateValues.numInputs).eq(1); + expect(stateVariables["/f"].stateValues.numOutputs).eq(2); + + let f1 = stateVariables["/f"].stateValues.fs[0]; + let f2 = stateVariables["/f"].stateValues.fs[1]; + let numericalf1 = stateVariables["/f"].stateValues.numericalfs[0]; + let numericalf2 = stateVariables["/f"].stateValues.numericalfs[1]; + let symbolicf1 = stateVariables["/f"].stateValues.symbolicfs[0]; + let symbolicf2 = stateVariables["/f"].stateValues.symbolicfs[1]; + + expect(f1(me.fromAst(-5)).equals(me.fromText("(-5)^2"))).eq(true); + expect(f2(me.fromAst(-5)).equals(me.fromText("(-5)^3"))).eq(true); + expect(f1(me.fromAst(3)).equals(me.fromText("3^2"))).eq(true); + expect(f2(me.fromAst(3)).equals(me.fromText("3^3"))).eq(true); + expect(f1(me.fromAst("z")).equals(me.fromText("z^2"))).eq(true); + expect(f2(me.fromAst("z")).equals(me.fromText("z^3"))).eq(true); + expect(numericalf1(-5)).closeTo(25, 1e-12); + expect(numericalf2(-5)).closeTo(-125, 1e-12); + expect(numericalf1(3)).closeTo(9, 1e-12); + expect(numericalf2(3)).closeTo(27, 1e-12); + expect(symbolicf1(me.fromAst(-5)).equals(me.fromText("(-5)^2"))).eq( + true, + ); + expect(symbolicf2(me.fromAst(-5)).equals(me.fromText("(-5)^3"))).eq( + true, + ); + expect(symbolicf1(me.fromAst(3)).equals(me.fromText("3^2"))).eq(true); + expect(symbolicf2(me.fromAst(3)).equals(me.fromText("3^3"))).eq(true); + expect(symbolicf1(me.fromAst("z")).equals(me.fromText("z^2"))).eq(true); + expect(symbolicf2(me.fromAst("z")).equals(me.fromText("z^3"))).eq(true); + } + + it("2D vector-valued function of a single variable", async () => { + let core = await createTestCore({ + doenetML: ` + (x^2, x^3) + `, + }); + + await test_2d_vector_function_single_var(core); + }); + + it("2D vector-valued function of a single variable, specify variable", async () => { + let core = await createTestCore({ + doenetML: ` + (t^2, t^3) + `, + }); + + await test_2d_vector_function_single_var(core); + }); + + it("2D vector-valued function of a single variable, specify numOutputs", async () => { + let core = await createTestCore({ + doenetML: ` + (t^2, t^3) + `, + }); + + await test_2d_vector_function_single_var(core); + }); + + async function test_3d_vector_function_single_var(core) { + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/f"].stateValues.numInputs).eq(1); + expect(stateVariables["/f"].stateValues.numOutputs).eq(3); + + let f1 = stateVariables["/f"].stateValues.fs[0]; + let f2 = stateVariables["/f"].stateValues.fs[1]; + let f3 = stateVariables["/f"].stateValues.fs[2]; + let numericalf1 = stateVariables["/f"].stateValues.numericalfs[0]; + let numericalf2 = stateVariables["/f"].stateValues.numericalfs[1]; + let numericalf3 = stateVariables["/f"].stateValues.numericalfs[2]; + let symbolicf1 = stateVariables["/f"].stateValues.symbolicfs[0]; + let symbolicf2 = stateVariables["/f"].stateValues.symbolicfs[1]; + let symbolicf3 = stateVariables["/f"].stateValues.symbolicfs[2]; + + expect(f1(me.fromAst(-5)).equals(me.fromText("(-5)^2"))).eq(true); + expect(f2(me.fromAst(-5)).equals(me.fromText("(-5)^3"))).eq(true); + expect(f3(me.fromAst(-5)).equals(me.fromText("(-5)^4"))).eq(true); + expect(f1(me.fromAst(3)).equals(me.fromText("3^2"))).eq(true); + expect(f2(me.fromAst(3)).equals(me.fromText("3^3"))).eq(true); + expect(f3(me.fromAst(3)).equals(me.fromText("3^4"))).eq(true); + expect(f1(me.fromAst("z")).equals(me.fromText("z^2"))).eq(true); + expect(f2(me.fromAst("z")).equals(me.fromText("z^3"))).eq(true); + expect(f3(me.fromAst("z")).equals(me.fromText("z^4"))).eq(true); + expect(numericalf1(-5)).closeTo(25, 1e-12); + expect(numericalf2(-5)).closeTo(-125, 1e-12); + expect(numericalf3(-5)).closeTo(625, 1e-12); + expect(numericalf1(3)).closeTo(9, 1e-12); + expect(numericalf2(3)).closeTo(27, 1e-12); + expect(numericalf3(3)).closeTo(81, 1e-12); + expect(symbolicf1(me.fromAst(-5)).equals(me.fromText("(-5)^2"))).eq( + true, + ); + expect(symbolicf2(me.fromAst(-5)).equals(me.fromText("(-5)^3"))).eq( + true, + ); + expect(symbolicf3(me.fromAst(-5)).equals(me.fromText("(-5)^4"))).eq( + true, + ); + expect(symbolicf1(me.fromAst(3)).equals(me.fromText("3^2"))).eq(true); + expect(symbolicf2(me.fromAst(3)).equals(me.fromText("3^3"))).eq(true); + expect(symbolicf3(me.fromAst(3)).equals(me.fromText("3^4"))).eq(true); + expect(symbolicf1(me.fromAst("z")).equals(me.fromText("z^2"))).eq(true); + expect(symbolicf2(me.fromAst("z")).equals(me.fromText("z^3"))).eq(true); + expect(symbolicf3(me.fromAst("z")).equals(me.fromText("z^4"))).eq(true); + } + + it("3D vector-valued function of a single variable", async () => { + let core = await createTestCore({ + doenetML: ` + (x^2, x^3, x^4) + `, + }); + + await test_3d_vector_function_single_var(core); + }); + + it("3D vector-valued function of a single variable, specify variable", async () => { + let core = await createTestCore({ + doenetML: ` + (t^2, t^3, t^4) + `, + }); + + await test_3d_vector_function_single_var(core); + }); + + it("2D vector-valued function of two variables", async () => { + let core = await createTestCore({ + doenetML: ` + (x^2y^3, x^3y^2) + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/f"].stateValues.numInputs).eq(2); + expect(stateVariables["/f"].stateValues.numOutputs).eq(2); + + let f1 = stateVariables["/f"].stateValues.fs[0]; + let f2 = stateVariables["/f"].stateValues.fs[1]; + let numericalf1 = stateVariables["/f"].stateValues.numericalfs[0]; + let numericalf2 = stateVariables["/f"].stateValues.numericalfs[1]; + let symbolicf1 = stateVariables["/f"].stateValues.symbolicfs[0]; + let symbolicf2 = stateVariables["/f"].stateValues.symbolicfs[1]; + + expect( + f1(me.fromAst(-5), me.fromAst(2)).equals(me.fromText("(-5)^2*2^3")), + ).eq(true); + expect( + f2(me.fromAst(-5), me.fromAst(2)).equals(me.fromText("(-5)^3*2^2")), + ).eq(true); + expect( + f1(me.fromAst(3), me.fromAst(-4)).equals(me.fromText("3^2*(-4)^3")), + ).eq(true); + expect( + f2(me.fromAst(3), me.fromAst(-4)).equals(me.fromText("3^3*(-4)^2")), + ).eq(true); + expect( + f1(me.fromAst("z"), me.fromAst("w")).equals(me.fromText("z^2w^3")), + ).eq(true); + expect( + f2(me.fromAst("z"), me.fromAst("w")).equals(me.fromText("z^3w^2")), + ).eq(true); + expect(numericalf1(-5, 2)).closeTo(200, 1e-12); + expect(numericalf2(-5, 2)).closeTo(-500, 1e-12); + expect(numericalf1(3, -4)).closeTo(-576, 1e-12); + expect(numericalf2(3, -4)).closeTo(432, 1e-12); + expect( + symbolicf1(me.fromAst(-5), me.fromAst(2)).equals( + me.fromText("(-5)^2*2^3"), + ), + ).eq(true); + expect( + symbolicf2(me.fromAst(-5), me.fromAst(2)).equals( + me.fromText("(-5)^3*2^2"), + ), + ).eq(true); + expect( + symbolicf1(me.fromAst(3), me.fromAst(-4)).equals( + me.fromText("3^2*(-4)^3"), + ), + ).eq(true); + expect( + symbolicf2(me.fromAst(3), me.fromAst(-4)).equals( + me.fromText("3^3*(-4)^2"), + ), + ).eq(true); + expect( + symbolicf1(me.fromAst("z"), me.fromAst("w")).equals( + me.fromText("z^2w^3"), + ), + ).eq(true); + expect( + symbolicf2(me.fromAst("z"), me.fromAst("w")).equals( + me.fromText("z^3w^2"), + ), + ).eq(true); + }); + + async function test_3d_vector_function_two_vars(core) { + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/f"].stateValues.numInputs).eq(2); + expect(stateVariables["/f"].stateValues.numOutputs).eq(3); + + let f1 = stateVariables["/f"].stateValues.fs[0]; + let f2 = stateVariables["/f"].stateValues.fs[1]; + let f3 = stateVariables["/f"].stateValues.fs[2]; + let numericalf1 = stateVariables["/f"].stateValues.numericalfs[0]; + let numericalf2 = stateVariables["/f"].stateValues.numericalfs[1]; + let numericalf3 = stateVariables["/f"].stateValues.numericalfs[2]; + let symbolicf1 = stateVariables["/f"].stateValues.symbolicfs[0]; + let symbolicf2 = stateVariables["/f"].stateValues.symbolicfs[1]; + let symbolicf3 = stateVariables["/f"].stateValues.symbolicfs[2]; + + expect(f1(-5, 2).equals(me.fromText("(-5)^2*2^3"))).eq(true); + expect(f2(-5, 2).equals(me.fromText("(-5)^3*2^2"))).eq(true); + expect(f3(-5, 2).equals(me.fromText("(-5)*2"))).eq(true); + expect(f1(3, -4).equals(me.fromText("3^2*(-4)^3"))).eq(true); + expect(f2(3, -4).equals(me.fromText("3^3*(-4)^2"))).eq(true); + expect(f3(3, -4).equals(me.fromText("3*(-4)"))).eq(true); + expect(f1("z", "w").equals(me.fromText("z^2w^3"))).eq(true); + expect(f2("z", "w").equals(me.fromText("z^3w^2"))).eq(true); + expect(f3("z", "w").equals(me.fromText("zw"))).eq(true); + expect(numericalf1(-5, 2)).closeTo(200, 1e-12); + expect(numericalf2(-5, 2)).closeTo(-500, 1e-12); + expect(numericalf3(-5, 2)).closeTo(-10, 1e-12); + expect(numericalf1(3, -4)).closeTo(-576, 1e-12); + expect(numericalf2(3, -4)).closeTo(432, 1e-12); + expect(numericalf3(3, -4)).closeTo(-12, 1e-12); + expect(symbolicf1(-5, 2).equals(me.fromText("(-5)^2*2^3"))).eq(true); + expect(symbolicf2(-5, 2).equals(me.fromText("(-5)^3*2^2"))).eq(true); + expect(symbolicf3(-5, 2).equals(me.fromText("(-5)*2"))).eq(true); + expect(symbolicf1(3, -4).equals(me.fromText("3^2*(-4)^3"))).eq(true); + expect(symbolicf2(3, -4).equals(me.fromText("3^3*(-4)^2"))).eq(true); + expect(symbolicf3(3, -4).equals(me.fromText("3*(-4)"))).eq(true); + expect(symbolicf1("z", "w").equals(me.fromText("z^2w^3"))).eq(true); + expect(symbolicf2("z", "w").equals(me.fromText("z^3w^2"))).eq(true); + expect(symbolicf3("z", "w").equals(me.fromText("zw"))).eq(true); + } + + it("3D vector-valued function of two variables", async () => { + let core = await createTestCore({ + doenetML: ` + (s^2t^3, s^3t^2, st) + `, + }); + + await test_3d_vector_function_two_vars(core); + }); + + it("3D vector-valued function of two variables, as alt vector", async () => { + let core = await createTestCore({ + doenetML: ` + ⟨s^2t^3, s^3t^2, st⟩ + `, + }); + + await test_3d_vector_function_two_vars(core); + }); + + it("copy function and overwrite symbolic attribute", async () => { + let core = await createTestCore({ + doenetML: ` + x^2 + + + x^2 + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/f1"].stateValues.symbolic).eq(false); + expect(stateVariables["/f2"].stateValues.symbolic).eq(true); + expect(stateVariables["/f3"].stateValues.symbolic).eq(false); + expect(stateVariables["/g1"].stateValues.symbolic).eq(true); + expect(stateVariables["/g2"].stateValues.symbolic).eq(false); + expect(stateVariables["/g3"].stateValues.symbolic).eq(true); + }); + + it("warnings on bad domain", async () => { + let core = await createTestCore({ + doenetML: ` + x + x + x + x + x + +

f1 domain:

+

f2 domain:

+

f3 domain:

+

f4 domain:

+

f5 domain:

+ + x+y + x+y + x+y + x+y + x+y + +

g1 domain: $g1.domain

+

g2 domain: $g2.domain

+

g3 domain: $g3.domain

+

g4 domain: $g4.domain

+

g5 domain: $g5.domain

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/domainf1"].stateValues.latex)).eq( + "(3,4)", + ); + expect(cleanLatex(stateVariables["/domainf2"].stateValues.latex)).eq( + "(-\\infty,\\infty)", + ); + expect(cleanLatex(stateVariables["/domainf3"].stateValues.latex)).eq( + "(-\\infty,\\infty)", + ); + expect(cleanLatex(stateVariables["/domainf4"].stateValues.latex)).eq( + "(-\\infty,\\infty)", + ); + expect(cleanLatex(stateVariables["/domainf5"].stateValues.latex)).eq( + "(3,4)", + ); + + expect(stateVariables["/pDomaing1"].stateValues.text).eq( + "g1 domain: ( -∞, ∞ ), ( -∞, ∞ )", + ); + expect(stateVariables["/pDomaing2"].stateValues.text).eq( + "g2 domain: ( 3, 4 ), ( 5, 6 )", + ); + expect(stateVariables["/pDomaing3"].stateValues.text).eq( + "g3 domain: ( -∞, ∞ ), ( -∞, ∞ )", + ); + expect(stateVariables["/pDomaing4"].stateValues.text).eq( + "g4 domain: ( -∞, ∞ ), ( -∞, ∞ )", + ); + expect(stateVariables["/pDomaing5"].stateValues.text).eq( + "g5 domain: ( 3, 4 ), ( 5, 6 )", + ); + + let errorWarnings = await core.errorWarnings; + + expect(errorWarnings.errors.length).eq(0); + expect(errorWarnings.warnings.length).eq(7); + + expect(errorWarnings.warnings[0].message).contain( + `Insufficient dimensions for domain for function. Domain has 0 intervals but the function has 1 input.`, + ); + expect(errorWarnings.warnings[0].level).eq(1); + expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(3); + expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(5); + expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(3); + expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(47); + + expect(errorWarnings.warnings[1].message).contain( + `Invalid format for domain for function`, + ); + expect(errorWarnings.warnings[1].level).eq(1); + expect(errorWarnings.warnings[1].doenetMLrange.lineBegin).eq(4); + expect(errorWarnings.warnings[1].doenetMLrange.charBegin).eq(5); + expect(errorWarnings.warnings[1].doenetMLrange.lineEnd).eq(4); + expect(errorWarnings.warnings[1].doenetMLrange.charEnd).eq(53); + + expect(errorWarnings.warnings[2].message).contain( + `Insufficient dimensions for domain for function. Domain has 0 intervals but the function has 1 input.`, + ); + expect(errorWarnings.warnings[2].level).eq(1); + expect(errorWarnings.warnings[2].doenetMLrange.lineBegin).eq(5); + expect(errorWarnings.warnings[2].doenetMLrange.charBegin).eq(5); + expect(errorWarnings.warnings[2].doenetMLrange.lineEnd).eq(5); + expect(errorWarnings.warnings[2].doenetMLrange.charEnd).eq(46); + + expect(errorWarnings.warnings[3].message).contain( + `Insufficient dimensions for domain for function. Domain has 1 interval but the function has 2 inputs.`, + ); + expect(errorWarnings.warnings[3].level).eq(1); + expect(errorWarnings.warnings[3].doenetMLrange.lineBegin).eq(14); + expect(errorWarnings.warnings[3].doenetMLrange.charBegin).eq(5); + expect(errorWarnings.warnings[3].doenetMLrange.lineEnd).eq(14); + expect(errorWarnings.warnings[3].doenetMLrange.charEnd).eq(67); + + expect(errorWarnings.warnings[4].message).contain( + `Invalid format for domain for function`, + ); + expect(errorWarnings.warnings[4].level).eq(1); + expect(errorWarnings.warnings[4].doenetMLrange.lineBegin).eq(16); + expect(errorWarnings.warnings[4].doenetMLrange.charBegin).eq(5); + expect(errorWarnings.warnings[4].doenetMLrange.lineEnd).eq(16); + expect(errorWarnings.warnings[4].doenetMLrange.charEnd).eq(75); + + expect(errorWarnings.warnings[5].message).contain( + `Insufficient dimensions for domain for function. Domain has 0 intervals but the function has 2 inputs.`, + ); + expect(errorWarnings.warnings[5].level).eq(1); + expect(errorWarnings.warnings[5].doenetMLrange.lineBegin).eq(17); + expect(errorWarnings.warnings[5].doenetMLrange.charBegin).eq(5); + expect(errorWarnings.warnings[5].doenetMLrange.lineEnd).eq(17); + expect(errorWarnings.warnings[5].doenetMLrange.charEnd).eq(62); + + expect(errorWarnings.warnings[6].message).contain( + `Invalid format for attribute domain of `, + ); + expect(errorWarnings.warnings[6].level).eq(1); + expect(errorWarnings.warnings[6].doenetMLrange.lineBegin).eq(3); + expect(errorWarnings.warnings[6].doenetMLrange.charBegin).eq(33); + expect(errorWarnings.warnings[6].doenetMLrange.lineEnd).eq(3); + expect(errorWarnings.warnings[6].doenetMLrange.charEnd).eq(33); + }); + + it("copy function and overwrite numInputs", async () => { + let core = await createTestCore({ + doenetML: ` + xyz + + + +

$$f1(a)

+

$$f2(a,b)

+

$$f3(a,b,c)

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/f1"].stateValues.numInputs).eq(1); + expect(stateVariables["/f2"].stateValues.numInputs).eq(2); + expect(stateVariables["/f3"].stateValues.numInputs).eq(3); + expect( + stateVariables["/f1"].stateValues.variables.map((x) => x.tree), + ).eqls(["x"]); + expect( + stateVariables["/f2"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y"]); + expect( + stateVariables["/f3"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y", "z"]); + + expect(stateVariables["/p1"].stateValues.text).eq("a y z"); + expect(stateVariables["/p2"].stateValues.text).eq("a b z"); + expect(stateVariables["/p3"].stateValues.text).eq("a b c"); + }); + + it("copy function and overwrite variables", async () => { + let core = await createTestCore({ + doenetML: ` + a + xyz + + + + + + +

$$f1(a)

+

$$f2(a,b)

+

$$f3(a,b,c)

+

$$f4(a,b)

+

$$f5(a)

+

$$f5a(a)

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/f1"].stateValues.numInputs).eq(1); + expect(stateVariables["/f2"].stateValues.numInputs).eq(2); + expect(stateVariables["/f3"].stateValues.numInputs).eq(3); + expect(stateVariables["/f4"].stateValues.numInputs).eq(2); + expect(stateVariables["/f5"].stateValues.numInputs).eq(1); + expect(stateVariables["/f5a"].stateValues.numInputs).eq(1); + expect( + stateVariables["/f1"].stateValues.variables.map((x) => x.tree), + ).eqls(["x"]); + expect( + stateVariables["/f2"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y"]); + expect( + stateVariables["/f3"].stateValues.variables.map((x) => x.tree), + ).eqls(["x", "y", "z"]); + expect( + stateVariables["/f4"].stateValues.variables.map((x) => x.tree), + ).eqls(["z", "y"]); + expect( + stateVariables["/f5"].stateValues.variables.map((x) => x.tree), + ).eqls(["y"]); + expect( + stateVariables["/f5a"].stateValues.variables.map((x) => x.tree), + ).eqls(["y"]); + + expect(stateVariables["/p1"].stateValues.text).eq("a y z"); + expect(stateVariables["/p2"].stateValues.text).eq("a b z"); + expect(stateVariables["/p3"].stateValues.text).eq("a b c"); + expect(stateVariables["/p4"].stateValues.text).eq("x b a"); + expect(stateVariables["/p5"].stateValues.text).eq("x a z"); + expect(stateVariables["/p5a"].stateValues.text).eq("x a z"); + }); + + async function test_prop_index(core) { + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/mn1"].stateValues.latex)).eq( + "(2,1)", + ); + expect(cleanLatex(stateVariables["/mx1"].stateValues.latex)).eq( + "(8,9)", + ); + expect(cleanLatex(stateVariables["/ex1"].stateValues.latex)).eq( + "(-4,4)", + ); + + expect(cleanLatex(stateVariables["/mnl1"].stateValues.latex)).eq("2"); + expect(cleanLatex(stateVariables["/mxl1"].stateValues.latex)).eq("8"); + expect(cleanLatex(stateVariables["/exl1"].stateValues.latex)).eq("-4"); + + expect(cleanLatex(stateVariables["/mnv1"].stateValues.latex)).eq("1"); + expect(cleanLatex(stateVariables["/mxv1"].stateValues.latex)).eq("9"); + expect(cleanLatex(stateVariables["/exv1"].stateValues.latex)).eq("4"); + + expect(cleanLatex(stateVariables["/mn11"].stateValues.latex)).eq("-5"); + expect(cleanLatex(stateVariables["/mx11"].stateValues.latex)).eq("4"); + expect(cleanLatex(stateVariables["/ex11"].stateValues.latex)).eq("-5"); + + // set propIndex to 1 + await updateMathInputValue({ latex: "1", componentName: "/n", core }); + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/mn1"].stateValues.latex)).eq( + "(-7,-5)", + ); + expect(cleanLatex(stateVariables["/mx1"].stateValues.latex)).eq( + "(-4,4)", + ); + expect(cleanLatex(stateVariables["/ex1"].stateValues.latex)).eq( + "(-7,-5)", + ); + + expect(cleanLatex(stateVariables["/mnl1"].stateValues.latex)).eq("-7"); + expect(cleanLatex(stateVariables["/mxl1"].stateValues.latex)).eq("-4"); + expect(cleanLatex(stateVariables["/exl1"].stateValues.latex)).eq("-7"); + + expect(cleanLatex(stateVariables["/mnv1"].stateValues.latex)).eq("-5"); + expect(cleanLatex(stateVariables["/mxv1"].stateValues.latex)).eq("4"); + expect(cleanLatex(stateVariables["/exv1"].stateValues.latex)).eq("-5"); + + expect(cleanLatex(stateVariables["/mn11"].stateValues.latex)).eq("-7"); + expect(cleanLatex(stateVariables["/mx11"].stateValues.latex)).eq("-4"); + expect(cleanLatex(stateVariables["/ex11"].stateValues.latex)).eq("-7"); + } + + it("copy props with propIndex, dot and array notation", async () => { + let core = await createTestCore({ + doenetML: ` +

n:

+ + + + + +

+

+

+ +

+

+

+ +

+

+

+ +

+

+

+ + `, + }); + + await test_prop_index(core); + }); + + it("copy props with multidimensional propIndex, dot and array notation", async () => { + let core = await createTestCore({ + doenetML: ` +

n:

+ + + + + +

+

+

+ +

+

+

+ +

+

+

+ +

+

+

+ + `, + }); + await test_prop_index(core); + }); + + it("rounding, overwrite on copy", async () => { + let core = await createTestCore({ + doenetML: ` + 255.029847 sin(0.52952342x) + 3 + 255.029847 sin(0.52952342x) + 3 + 255.029847 sin(0.52952342x) + 3 + 255.029847 sin(0.52952342x) + 3 + 255.029847 sin(0.52952342x) + 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $f1 + $f2 + $f3 + $f4 + $f5 + $f1 + $f2 + $f3 + $f4 + $f5 + $f1 + $f2 + $f3 + $f4 + $f5 + $f1 + $f2 + $f3 + $f4 + $f5 + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/f1"].stateValues.latex)).eq( + "255.03\\sin(0.53x)+3", + ); + expect(cleanLatex(stateVariables["/f2"].stateValues.latex)).eq( + "255\\sin(0.5295x)+3", + ); + expect(cleanLatex(stateVariables["/f3"].stateValues.latex)).eq( + "255.0\\sin(0.5295x)+3.000", + ); + expect(cleanLatex(stateVariables["/f4"].stateValues.latex)).eq( + "255.03\\sin(0.53x)+3", + ); + expect(cleanLatex(stateVariables["/f5"].stateValues.latex)).eq( + "255.030\\sin(0.530x)+3.000", + ); + + expect(cleanLatex(stateVariables["/f1dg6"].stateValues.latex)).eq( + "255.03\\sin(0.529523x)+3", + ); + expect(cleanLatex(stateVariables["/f2dg6"].stateValues.latex)).eq( + "255.03\\sin(0.529523x)+3", + ); + expect(cleanLatex(stateVariables["/f3dg6"].stateValues.latex)).eq( + "255.030\\sin(0.529523x)+3.00000", + ); + expect(cleanLatex(stateVariables["/f4dg6"].stateValues.latex)).eq( + "255.03\\sin(0.529523x)+3", + ); + expect(cleanLatex(stateVariables["/f5dg6"].stateValues.latex)).eq( + "255.030\\sin(0.529523x)+3.00000", + ); + + expect(cleanLatex(stateVariables["/f1fdg6"].stateValues.latex)).eq( + "255.03\\sin(0.529523x)+3", + ); + expect(cleanLatex(stateVariables["/f2fdg6"].stateValues.latex)).eq( + "255.03\\sin(0.529523x)+3", + ); + expect(cleanLatex(stateVariables["/f3fdg6"].stateValues.latex)).eq( + "255.030\\sin(0.529523x)+3.00000", + ); + expect(cleanLatex(stateVariables["/f4fdg6"].stateValues.latex)).eq( + "255.03\\sin(0.529523x)+3", + ); + expect(cleanLatex(stateVariables["/f5fdg6"].stateValues.latex)).eq( + "255.030\\sin(0.529523x)+3.00000", + ); + + expect(cleanLatex(stateVariables["/f1dg6a"].stateValues.latex)).eq( + "255.03\\sin(0.529523x)+3", + ); + expect(cleanLatex(stateVariables["/f2dg6a"].stateValues.latex)).eq( + "255.03\\sin(0.529523x)+3", + ); + expect(cleanLatex(stateVariables["/f3dg6a"].stateValues.latex)).eq( + "255.030\\sin(0.529523x)+3.00000", + ); + expect(cleanLatex(stateVariables["/f4dg6a"].stateValues.latex)).eq( + "255.03\\sin(0.529523x)+3", + ); + expect(cleanLatex(stateVariables["/f5dg6a"].stateValues.latex)).eq( + "255.030\\sin(0.529523x)+3.00000", + ); + + expect(cleanLatex(stateVariables["/f1dc7"].stateValues.latex)).eq( + "255.029847\\sin(0.5295234x)+3", + ); + expect(cleanLatex(stateVariables["/f2dc7"].stateValues.latex)).eq( + "255.029847\\sin(0.5295234x)+3", + ); + expect(cleanLatex(stateVariables["/f3dc7"].stateValues.latex)).eq( + "255.0298470\\sin(0.5295234x)+3.0000000", + ); + expect(cleanLatex(stateVariables["/f4dc7"].stateValues.latex)).eq( + "255.029847\\sin(0.5295234x)+3", + ); + expect(cleanLatex(stateVariables["/f5dc7"].stateValues.latex)).eq( + "255.0298470\\sin(0.5295234x)+3.0000000", + ); + + expect(cleanLatex(stateVariables["/f1fdc7"].stateValues.latex)).eq( + "255.029847\\sin(0.5295234x)+3", + ); + expect(cleanLatex(stateVariables["/f2fdc7"].stateValues.latex)).eq( + "255.029847\\sin(0.5295234x)+3", + ); + expect(cleanLatex(stateVariables["/f3fdc7"].stateValues.latex)).eq( + "255.0298470\\sin(0.5295234x)+3.0000000", + ); + expect(cleanLatex(stateVariables["/f4fdc7"].stateValues.latex)).eq( + "255.029847\\sin(0.5295234x)+3", + ); + expect(cleanLatex(stateVariables["/f5fdc7"].stateValues.latex)).eq( + "255.0298470\\sin(0.5295234x)+3.0000000", + ); + + expect(cleanLatex(stateVariables["/f1dc7a"].stateValues.latex)).eq( + "255.029847\\sin(0.5295234x)+3", + ); + expect(cleanLatex(stateVariables["/f2dc7a"].stateValues.latex)).eq( + "255.029847\\sin(0.5295234x)+3", + ); + expect(cleanLatex(stateVariables["/f3dc7a"].stateValues.latex)).eq( + "255.0298470\\sin(0.5295234x)+3.0000000", + ); + expect(cleanLatex(stateVariables["/f4dc7a"].stateValues.latex)).eq( + "255.029847\\sin(0.5295234x)+3", + ); + expect(cleanLatex(stateVariables["/f5dc7a"].stateValues.latex)).eq( + "255.0298470\\sin(0.5295234x)+3.0000000", + ); + + expect(cleanLatex(stateVariables["/f1pt"].stateValues.latex)).eq( + "255.03\\sin(0.530x)+3.00", + ); + expect(cleanLatex(stateVariables["/f2pt"].stateValues.latex)).eq( + "255.0\\sin(0.5295x)+3.000", + ); + expect(cleanLatex(stateVariables["/f3pt"].stateValues.latex)).eq( + "255.0\\sin(0.5295x)+3.000", + ); + expect(cleanLatex(stateVariables["/f4pt"].stateValues.latex)).eq( + "255.030\\sin(0.530x)+3.000", + ); + expect(cleanLatex(stateVariables["/f5pt"].stateValues.latex)).eq( + "255.030\\sin(0.530x)+3.000", + ); + + expect(cleanLatex(stateVariables["/f1fpt"].stateValues.latex)).eq( + "255.03\\sin(0.530x)+3.00", + ); + expect(cleanLatex(stateVariables["/f2fpt"].stateValues.latex)).eq( + "255.0\\sin(0.5295x)+3.000", + ); + expect(cleanLatex(stateVariables["/f3fpt"].stateValues.latex)).eq( + "255.0\\sin(0.5295x)+3.000", + ); + expect(cleanLatex(stateVariables["/f4fpt"].stateValues.latex)).eq( + "255.030\\sin(0.530x)+3.000", + ); + expect(cleanLatex(stateVariables["/f5fpt"].stateValues.latex)).eq( + "255.030\\sin(0.530x)+3.000", + ); + + expect(cleanLatex(stateVariables["/f1pta"].stateValues.latex)).eq( + "255.03\\sin(0.530x)+3.00", + ); + expect(cleanLatex(stateVariables["/f2pta"].stateValues.latex)).eq( + "255.0\\sin(0.5295x)+3.000", + ); + expect(cleanLatex(stateVariables["/f3pta"].stateValues.latex)).eq( + "255.0\\sin(0.5295x)+3.000", + ); + expect(cleanLatex(stateVariables["/f4pta"].stateValues.latex)).eq( + "255.030\\sin(0.530x)+3.000", + ); + expect(cleanLatex(stateVariables["/f5pta"].stateValues.latex)).eq( + "255.030\\sin(0.530x)+3.000", + ); + + expect(cleanLatex(stateVariables["/f1pf"].stateValues.latex)).eq( + "255.03\\sin(0.53x)+3", + ); + expect(cleanLatex(stateVariables["/f2pf"].stateValues.latex)).eq( + "255\\sin(0.5295x)+3", + ); + expect(cleanLatex(stateVariables["/f3pf"].stateValues.latex)).eq( + "255\\sin(0.5295x)+3", + ); + expect(cleanLatex(stateVariables["/f4pf"].stateValues.latex)).eq( + "255.03\\sin(0.53x)+3", + ); + expect(cleanLatex(stateVariables["/f5pf"].stateValues.latex)).eq( + "255.03\\sin(0.53x)+3", + ); + + expect(cleanLatex(stateVariables["/f1fpf"].stateValues.latex)).eq( + "255.03\\sin(0.53x)+3", + ); + expect(cleanLatex(stateVariables["/f2fpf"].stateValues.latex)).eq( + "255\\sin(0.5295x)+3", + ); + expect(cleanLatex(stateVariables["/f3fpf"].stateValues.latex)).eq( + "255\\sin(0.5295x)+3", + ); + expect(cleanLatex(stateVariables["/f4fpf"].stateValues.latex)).eq( + "255.03\\sin(0.53x)+3", + ); + expect(cleanLatex(stateVariables["/f5fpf"].stateValues.latex)).eq( + "255.03\\sin(0.53x)+3", + ); + + expect(cleanLatex(stateVariables["/f1pfa"].stateValues.latex)).eq( + "255.03\\sin(0.53x)+3", + ); + expect(cleanLatex(stateVariables["/f2pfa"].stateValues.latex)).eq( + "255\\sin(0.5295x)+3", + ); + expect(cleanLatex(stateVariables["/f3pfa"].stateValues.latex)).eq( + "255\\sin(0.5295x)+3", + ); + expect(cleanLatex(stateVariables["/f4pfa"].stateValues.latex)).eq( + "255.03\\sin(0.53x)+3", + ); + expect(cleanLatex(stateVariables["/f5pfa"].stateValues.latex)).eq( + "255.03\\sin(0.53x)+3", + ); + }); + + it("handle bad through and other defining attributes", async () => { + let core = await createTestCore({ + doenetML: ` + a + + `, + }); + + // page loads + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/t1"].stateValues.value).eq("a"); + }); + + it("extrema shadow style number", async () => { + let core = await createTestCore({ + doenetML: ` + x^3-x + + + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/max"].stateValues.styleNumber).eq(2); + expect(stateVariables["/min"].stateValues.styleNumber).eq(2); + expect(stateVariables["/ext1"].stateValues.styleNumber).eq(2); + expect(stateVariables["/ext2"].stateValues.styleNumber).eq(2); + expect(stateVariables["/gmax"].stateValues.styleNumber).eq(2); + expect(stateVariables["/gmin"].stateValues.styleNumber).eq(2); + expect(stateVariables["/sup"].stateValues.styleNumber).eq(2); + expect(stateVariables["/inf"].stateValues.styleNumber).eq(2); + }); + + it("check bugfix: don't get invalid maxima due having incorrect derivative with function of interpolated function", async () => { + let core = await createTestCore({ + doenetML: ` + + $$f(x)-x^4 + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/max1"].stateValues.xs.map((x) => x.tree)).eqls([ + 1, -1, + ]); + expect(stateVariables["/max2"]).eq(undefined); + expect(stateVariables["/min"]).eq(undefined); + expect(stateVariables["/ext1"].stateValues.xs.map((x) => x.tree)).eqls([ + 1, -1, + ]); + expect(stateVariables["/ext2"]).eq(undefined); + }); + + it("check bugfix: don't get invalid extrema due to roundoff error with function of interpolated function", async () => { + let core = await createTestCore({ + doenetML: ` + + $$f(x)+(x-3)^2 + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/max"]).eq(undefined); + expect(stateVariables["/min"]).eq(undefined); + expect(stateVariables["/ext"]).eq(undefined); + }); + + it("global extrema, double well, test all properties", async () => { + let core = await createTestCore({ + doenetML: ` + x^4-8x^2+8 +

domain:

+

min results for f: $f.globalMinimum{assignNames="fmin"}, $f.globalMinimumLocation{assignNames="fminl"}, $f.globalMinimumValue{assignNames="fminv"}, $f.globalMinimum[1]{assignNames="fminla"}, $f.globalMinimum[2]{assignNames="fminva"}

+

min compactify results for f: $f.globalInfimum{assignNames="fmincd"}, $f.globalInfimumLocation{assignNames="fmincdl"}, $f.globalInfimumValue{assignNames="fmincdv"}, $f.globalInfimum[1]{assignNames="fmincdla"}, $f.globalInfimum[2]{assignNames="fmincdva"}

+

max results for f: $f.globalMaximum{assignNames="fmax"}, $f.globalMaximumLocation{assignNames="fmaxl"}, $f.globalMaximumValue{assignNames="fmaxv"}, $f.globalMaximum[1]{assignNames="fmaxla"}, $f.globalMaximum[2]{assignNames="fmaxva"}

+

max compactify results for f: $f.globalSupremum{assignNames="fmaxcd"}, $f.globalSupremumLocation{assignNames="fmaxcdl"}, $f.globalSupremumValue{assignNames="fmaxcdv"}, $f.globalSupremum[1]{assignNames="fmaxcdla"}, $f.globalSupremum[2]{assignNames="fmaxcdva"}

+ `, + }); + + let f100 = 100 ** 4 - 8 * 100 ** 2 + 8; + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/f"].stateValues.domain.map((x) => x.tree)).eqls( + [ + [ + "interval", + ["tuple", -Infinity, Infinity], + ["tuple", false, false], + ], + ], + ); + + expect(stateVariables["/fmin"].stateValues.xs.map((x) => x.tree)).eqls([ + -2, -8, + ]); + expect(stateVariables["/fminl"].stateValues.value).eq(-2); + expect(stateVariables["/fminla"].stateValues.value).eq(-2); + expect(stateVariables["/fminv"].stateValues.value).eq(-8); + expect(stateVariables["/fminva"].stateValues.value).eq(-8); + + expect( + stateVariables["/fmincd"].stateValues.xs.map((x) => x.tree), + ).eqls([-2, -8]); + expect(stateVariables["/fmincdl"].stateValues.value).eq(-2); + expect(stateVariables["/fmincdla"].stateValues.value).eq(-2); + expect(stateVariables["/fmincdv"].stateValues.value).eq(-8); + expect(stateVariables["/fmincdva"].stateValues.value).eq(-8); + + expect(stateVariables["/fmax"]).eq(undefined); + expect(stateVariables["/fmaxl"].stateValues.value).eqls(NaN); + expect(stateVariables["/fmaxla"].stateValues.value).eqls(NaN); + expect(stateVariables["/fmaxv"].stateValues.value).eqls(NaN); + expect(stateVariables["/fmaxva"].stateValues.value).eqls(NaN); + + expect( + stateVariables["/fmaxcd"].stateValues.xs.map((x) => x.tree), + ).eqls([-100, f100]); + expect(stateVariables["/fmaxcdl"].stateValues.value).eq(-100); + expect(stateVariables["/fmaxcdla"].stateValues.value).eq(-100); + expect(stateVariables["/fmaxcdv"].stateValues.value).eq(f100); + expect(stateVariables["/fmaxcdva"].stateValues.value).eq(f100); + }); + + it("global extrema, double well, different domains", async () => { + let core = await createTestCore({ + doenetML: ` + x^4-8x^2+8 + x^4-8x^2+8 + x^4-8x^2+8 + x^4-8x^2+8 + x^4-8x^2+8 + +

f1: $f1.globalMinimum{assignNames="f1min"}, $f1.globalInfimum{assignNames="f1mincd"}, $f1.globalMaximum{assignNames="f1max"}, $f1.globalSupremum{assignNames="f1maxcd"}

+

f2: $f2.globalMinimum{assignNames="f2min"}, $f2.globalInfimum{assignNames="f2mincd"}, $f2.globalMaximum{assignNames="f2max"}, $f2.globalSupremum{assignNames="f2maxcd"}

+

f3: $f3.globalMinimum{assignNames="f3min"}, $f3.globalInfimum{assignNames="f3mincd"}, $f3.globalMaximum{assignNames="f3max"}, $f3.globalSupremum{assignNames="f3maxcd"}

+

f4: $f4.globalMinimum{assignNames="f4min"}, $f4.globalInfimum{assignNames="f4mincd"}, $f4.globalMaximum{assignNames="f4max"}, $f4.globalSupremum{assignNames="f4maxcd"}

+

f5: $f5.globalMinimum{assignNames="f5min"}, $f5.globalInfimum{assignNames="f5mincd"}, $f5.globalMaximum{assignNames="f5max"}, $f5.globalSupremum{assignNames="f5maxcd"}

+ `, + }); + + let f198 = 198 ** 4 - 8 * 198 ** 2 + 8; + + let stateVariables = await returnAllStateVariables(core); + + expect( + stateVariables["/f1"].stateValues.domain.map((x) => x.tree), + ).eqls([ + ["interval", ["tuple", -2, Infinity], ["tuple", false, false]], + ]); + expect( + stateVariables["/f2"].stateValues.domain.map((x) => x.tree), + ).eqls([ + ["interval", ["tuple", -Infinity, 2], ["tuple", false, false]], + ]); + expect( + stateVariables["/f3"].stateValues.domain.map((x) => x.tree), + ).eqls([["interval", ["tuple", 0, 2], ["tuple", false, true]]]); + expect( + stateVariables["/f4"].stateValues.domain.map((x) => x.tree), + ).eqls([["interval", ["tuple", 0, 2], ["tuple", true, false]]]); + expect( + stateVariables["/f5"].stateValues.domain.map((x) => x.tree), + ).eqls([["interval", ["tuple", -0.01, 2.01], ["tuple", false, false]]]); + + expect(stateVariables["/f1min"].stateValues.xs.map((x) => x.tree)).eqls( + [2, -8], + ); + expect( + stateVariables["/f1mincd"].stateValues.xs.map((x) => x.tree), + ).eqls([2, -8]); + expect(stateVariables["/f1max"]).eq(undefined); + expect( + stateVariables["/f1maxcd"].stateValues.xs.map((x) => x.tree), + ).eqls([198, f198]); + + expect(stateVariables["/f2min"].stateValues.xs.map((x) => x.tree)).eqls( + [-2, -8], + ); + expect( + stateVariables["/f2mincd"].stateValues.xs.map((x) => x.tree), + ).eqls([-2, -8]); + expect(stateVariables["/f2max"]).eq(undefined); + expect( + stateVariables["/f2maxcd"].stateValues.xs.map((x) => x.tree), + ).eqls([-198, f198]); + + expect(stateVariables["/f3min"].stateValues.xs.map((x) => x.tree)).eqls( + [2, -8], + ); + expect( + stateVariables["/f3mincd"].stateValues.xs.map((x) => x.tree), + ).eqls([2, -8]); + expect(stateVariables["/f3max"]).eq(undefined); + expect( + stateVariables["/f3maxcd"].stateValues.xs.map((x) => x.tree), + ).eqls([0, 8]); + + expect(stateVariables["/f4min"]).eq(undefined); + expect( + stateVariables["/f4mincd"].stateValues.xs.map((x) => x.tree), + ).eqls([2, -8]); + expect(stateVariables["/f4max"].stateValues.xs.map((x) => x.tree)).eqls( + [0, 8], + ); + expect( + stateVariables["/f4maxcd"].stateValues.xs.map((x) => x.tree), + ).eqls([0, 8]); + + expect(stateVariables["/f5min"].stateValues.xs[0].tree).closeTo( + 2, + 1e-5, + ); + expect(stateVariables["/f5min"].stateValues.xs[1].tree).closeTo( + -8, + 1e-5, + ); + expect(stateVariables["/f5mincd"].stateValues.xs[0].tree).closeTo( + 2, + 1e-5, + ); + expect(stateVariables["/f5mincd"].stateValues.xs[1].tree).closeTo( + -8, + 1e-5, + ); + expect(stateVariables["/f5max"].stateValues.xs[0].tree).closeTo( + 0, + 1e-5, + ); + expect(stateVariables["/f5max"].stateValues.xs[1].tree).closeTo( + 8, + 1e-5, + ); + expect(stateVariables["/f5maxcd"].stateValues.xs[0].tree).closeTo( + 0, + 1e-5, + ); + expect(stateVariables["/f5maxcd"].stateValues.xs[1].tree).closeTo( + 8, + 1e-5, + ); + }); + + it("global extrema, sin, different domains", async () => { + let core = await createTestCore({ + doenetML: ` + sin(x) + sin(x) + sin(x) + sin(x) + sin(x) +

f1: $f1.globalMinimum{assignNames="f1min"}, $f1.globalInfimum{assignNames="f1mincd"}, $f1.globalMaximum{assignNames="f1max"}, $f1.globalSupremum{assignNames="f1maxcd"}

+

f2: $f2.globalMinimum{assignNames="f2min"}, $f2.globalInfimum{assignNames="f2mincd"}, $f2.globalMaximum{assignNames="f2max"}, $f2.globalSupremum{assignNames="f2maxcd"}

+

f3: $f3.globalMinimum{assignNames="f3min"}, $f3.globalInfimum{assignNames="f3mincd"}, $f3.globalMaximum{assignNames="f3max"}, $f3.globalSupremum{assignNames="f3maxcd"}

+

f4: $f4.globalMinimum{assignNames="f4min"}, $f4.globalInfimum{assignNames="f4mincd"}, $f4.globalMaximum{assignNames="f4max"}, $f4.globalSupremum{assignNames="f4maxcd"}

+

f5: $f5.globalMinimum{assignNames="f5min"}, $f5.globalInfimum{assignNames="f5mincd"}, $f5.globalMaximum{assignNames="f5max"}, $f5.globalSupremum{assignNames="f5maxcd"}

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/f1min"].stateValues.xs.map((x) => x.tree)).eqls( + [-Math.PI / 2, -1], + ); + expect( + stateVariables["/f1mincd"].stateValues.xs.map((x) => x.tree), + ).eqls([-Math.PI / 2, -1]); + expect(stateVariables["/f1max"].stateValues.xs.map((x) => x.tree)).eqls( + [Math.PI / 2, 1], + ); + expect( + stateVariables["/f1maxcd"].stateValues.xs.map((x) => x.tree), + ).eqls([Math.PI / 2, 1]); + + expect(stateVariables["/f2min"]).eq(undefined); + expect( + stateVariables["/f2mincd"].stateValues.xs.map((x) => x.tree), + ).eqls([-Math.PI / 2, -1]); + expect(stateVariables["/f2max"].stateValues.xs.map((x) => x.tree)).eqls( + [Math.PI / 2, 1], + ); + expect( + stateVariables["/f2maxcd"].stateValues.xs.map((x) => x.tree), + ).eqls([Math.PI / 2, 1]); + + expect(stateVariables["/f3min"].stateValues.xs.map((x) => x.tree)).eqls( + [(3 * Math.PI) / 2, -1], + ); + expect( + stateVariables["/f3mincd"].stateValues.xs.map((x) => x.tree), + ).eqls([(3 * Math.PI) / 2, -1]); + expect(stateVariables["/f3max"].stateValues.xs.map((x) => x.tree)).eqls( + [Math.PI / 2, 1], + ); + expect( + stateVariables["/f3maxcd"].stateValues.xs.map((x) => x.tree), + ).eqls([Math.PI / 2, 1]); + + expect(stateVariables["/f4min"]).eq(undefined); + expect( + stateVariables["/f4mincd"].stateValues.xs.map((x) => x.tree), + ).eqls([-Math.PI / 2, -1]); + expect(stateVariables["/f4max"]).eq(undefined); + expect( + stateVariables["/f4maxcd"].stateValues.xs.map((x) => x.tree), + ).eqls([Math.PI / 2, 1]); + + expect(stateVariables["/f5min"].stateValues.xs.map((x) => x.tree)).eqls( + [-Math.PI / 2, -1], + ); + expect( + stateVariables["/f5mincd"].stateValues.xs.map((x) => x.tree), + ).eqls([-Math.PI / 2, -1]); + expect(stateVariables["/f5max"].stateValues.xs.map((x) => x.tree)).eqls( + [Math.PI / 2, 1], + ); + expect( + stateVariables["/f5maxcd"].stateValues.xs.map((x) => x.tree), + ).eqls([Math.PI / 2, 1]); + }); + + it("global extrema, 1/x, different domains", async () => { + let core = await createTestCore({ + doenetML: ` + 1/x + 1/x + 1/x + 1/x + -1/x +

f1: $f1.globalMinimum{assignNames="f1min"}, $f1.globalInfimum{assignNames="f1mincd"}, $f1.globalMaximum{assignNames="f1max"}, $f1.globalSupremum{assignNames="f1maxcd"}

+

f2: $f2.globalMinimum{assignNames="f2min"}, $f2.globalInfimum{assignNames="f2mincd"}, $f2.globalMaximum{assignNames="f2max"}, $f2.globalSupremum{assignNames="f2maxcd"}

+

f3: $f3.globalMinimum{assignNames="f3min"}, $f3.globalInfimum{assignNames="f3mincd"}, $f3.globalMaximum{assignNames="f3max"}, $f3.globalSupremum{assignNames="f3maxcd"}

+

f4: $f4.globalMinimum{assignNames="f4min"}, $f4.globalInfimum{assignNames="f4mincd"}, $f4.globalMaximum{assignNames="f4max"}, $f4.globalSupremum{assignNames="f4maxcd"}

+

f5: $f5.globalMinimum{assignNames="f5min"}, $f5.globalInfimum{assignNames="f5mincd"}, $f5.globalMaximum{assignNames="f5max"}, $f5.globalSupremum{assignNames="f5maxcd"}

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/f1min"].stateValues.xs[0].tree).within( + -1e-6, + -1e-300, + ); + expect(stateVariables["/f1min"].stateValues.xs[1].tree).lessThan(-1e6); + expect( + stateVariables["/f1mincd"].stateValues.xs.map((x) => x.tree), + ).eqls(stateVariables["/f1min"].stateValues.xs.map((x) => x.tree)); + expect(stateVariables["/f1max"].stateValues.xs[0].tree).within( + 1e-300, + 1e-6, + ); + expect(stateVariables["/f1max"].stateValues.xs[1].tree).greaterThan( + 1e6, + ); + expect( + stateVariables["/f1maxcd"].stateValues.xs.map((x) => x.tree), + ).eqls(stateVariables["/f1max"].stateValues.xs.map((x) => x.tree)); + + expect(stateVariables["/f2min"]).eq(undefined); + expect( + stateVariables["/f2mincd"].stateValues.xs.map((x) => x.tree), + ).eqls([200, 1 / 200]); + expect(stateVariables["/f2max"]).eq(undefined); + expect( + stateVariables["/f2maxcd"].stateValues.xs.map((x) => x.tree), + ).eqls([0, Infinity]); + + expect(stateVariables["/f3min"]).eq(undefined); + expect( + stateVariables["/f3mincd"].stateValues.xs.map((x) => x.tree), + ).eqls([0, -Infinity]); + expect(stateVariables["/f3max"]).eq(undefined); + expect( + stateVariables["/f3maxcd"].stateValues.xs.map((x) => x.tree), + ).eqls([-200, -1 / 200]); + + expect(stateVariables["/f4min"].stateValues.xs[0].tree).within( + -1e-6, + -1e-300, + ); + expect(stateVariables["/f4min"].stateValues.xs[1].tree).lessThan(-1e6); + expect( + stateVariables["/f4mincd"].stateValues.xs.map((x) => x.tree), + ).eqls(stateVariables["/f4min"].stateValues.xs.map((x) => x.tree)); + expect(stateVariables["/f4max"].stateValues.xs[0].tree).within( + 1e-300, + 1e-6, + ); + expect(stateVariables["/f4max"].stateValues.xs[1].tree).greaterThan( + 1e6, + ); + expect( + stateVariables["/f4maxcd"].stateValues.xs.map((x) => x.tree), + ).eqls(stateVariables["/f4max"].stateValues.xs.map((x) => x.tree)); + + expect(stateVariables["/f5min"]).eq(undefined); + expect( + stateVariables["/f5mincd"].stateValues.xs.map((x) => x.tree), + ).eqls([-1, 1]); + expect(stateVariables["/f5max"]).eq(undefined); + expect( + stateVariables["/f5maxcd"].stateValues.xs.map((x) => x.tree), + ).eqls([0, Infinity]); + }); + + it("global extrema, 1/x^2, different domains", async () => { + let core = await createTestCore({ + doenetML: ` + 1/x^2 + 1/x^2 + 1/x^2 + 1/x^2 + -1/x^2 +

f1: $f1.globalMinimum{assignNames="f1min"}, $f1.globalInfimum{assignNames="f1mincd"}, $f1.globalMaximum{assignNames="f1max"}, $f1.globalSupremum{assignNames="f1maxcd"}

+

f2: $f2.globalMinimum{assignNames="f2min"}, $f2.globalInfimum{assignNames="f2mincd"}, $f2.globalMaximum{assignNames="f2max"}, $f2.globalSupremum{assignNames="f2maxcd"}

+

f3: $f3.globalMinimum{assignNames="f3min"}, $f3.globalInfimum{assignNames="f3mincd"}, $f3.globalMaximum{assignNames="f3max"}, $f3.globalSupremum{assignNames="f3maxcd"}

+

f4: $f4.globalMinimum{assignNames="f4min"}, $f4.globalInfimum{assignNames="f4mincd"}, $f4.globalMaximum{assignNames="f4max"}, $f4.globalSupremum{assignNames="f4maxcd"}

+

f5: $f5.globalMinimum{assignNames="f5min"}, $f5.globalInfimum{assignNames="f5mincd"}, $f5.globalMaximum{assignNames="f5max"}, $f5.globalSupremum{assignNames="f5maxcd"}

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/f1min"]).eq(undefined); + expect( + stateVariables["/f1mincd"].stateValues.xs.map((x) => x.tree), + ).eqls([-100, 1 / 10000]); + expect(stateVariables["/f1max"].stateValues.xs[0].tree).within( + -1e-6, + -1e-300, + ); + expect(stateVariables["/f1max"].stateValues.xs[1].tree).greaterThan( + 1e12, + ); + expect( + stateVariables["/f1maxcd"].stateValues.xs.map((x) => x.tree), + ).eqls(stateVariables["/f1max"].stateValues.xs.map((x) => x.tree)); + + expect(stateVariables["/f2min"]).eq(undefined); + expect( + stateVariables["/f2mincd"].stateValues.xs.map((x) => x.tree), + ).eqls([200, 1 / 40000]); + expect(stateVariables["/f2max"]).eq(undefined); + expect( + stateVariables["/f2maxcd"].stateValues.xs.map((x) => x.tree), + ).eqls([0, Infinity]); + + expect(stateVariables["/f3min"]).eq(undefined); + expect( + stateVariables["/f3mincd"].stateValues.xs.map((x) => x.tree), + ).eqls([-200, 1 / 40000]); + expect(stateVariables["/f3max"]).eq(undefined); + expect( + stateVariables["/f3maxcd"].stateValues.xs.map((x) => x.tree), + ).eqls([0, Infinity]); + + expect(stateVariables["/f4min"]).eq(undefined); + expect( + stateVariables["/f4mincd"].stateValues.xs.map((x) => x.tree), + ).eqls([100, 1 / 10000]); + expect(stateVariables["/f4max"].stateValues.xs[0].tree).within( + -1e-6, + -1e-300, + ); + expect(stateVariables["/f4max"].stateValues.xs[1].tree).greaterThan( + 1e12, + ); + expect( + stateVariables["/f4maxcd"].stateValues.xs.map((x) => x.tree), + ).eqls(stateVariables["/f4max"].stateValues.xs.map((x) => x.tree)); + + expect(stateVariables["/f5min"]).eq(undefined); + expect( + stateVariables["/f5mincd"].stateValues.xs.map((x) => x.tree), + ).eqls([0, -Infinity]); + expect(stateVariables["/f5max"]).eq(undefined); + expect( + stateVariables["/f5maxcd"].stateValues.xs.map((x) => x.tree), + ).eqls([-1, -1]); + }); + + it("global extrema of linear interpolated function", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let f1 = stateVariables["/f1"]; + let f2 = stateVariables["/f2"]; + let f3 = stateVariables["/f3"]; + let f4 = stateVariables["/f4"]; + let f5 = stateVariables["/f5"]; + let f6 = stateVariables["/f6"]; + let f7 = stateVariables["/f7"]; + let f8 = stateVariables["/f8"]; + + expect(f1.stateValues.domain.map((x) => x.tree)).eqls([ + [ + "interval", + ["tuple", -Infinity, Infinity], + ["tuple", false, false], + ], + ]); + expect(f2.stateValues.domain.map((x) => x.tree)).eqls([ + [ + "interval", + ["tuple", -Infinity, Infinity], + ["tuple", false, false], + ], + ]); + expect(f3.stateValues.domain.map((x) => x.tree)).eqls([ + ["interval", ["tuple", -10, -9], ["tuple", false, false]], + ]); + expect(f4.stateValues.domain.map((x) => x.tree)).eqls([ + ["interval", ["tuple", -7, 3], ["tuple", true, true]], + ]); + expect(f5.stateValues.domain.map((x) => x.tree)).eqls([ + ["interval", ["tuple", 9, 10], ["tuple", false, true]], + ]); + expect(f6.stateValues.domain.map((x) => x.tree)).eqls([ + ["interval", ["tuple", -10, -9], ["tuple", false, false]], + ]); + expect(f7.stateValues.domain.map((x) => x.tree)).eqls([ + ["interval", ["tuple", -7, 3], ["tuple", true, true]], + ]); + expect(f8.stateValues.domain.map((x) => x.tree)).eqls([ + ["interval", ["tuple", 9, 10], ["tuple", false, true]], + ]); + + expect(f1.stateValues.globalMinimum).eqls([]); + expect(f1.stateValues.globalInfimum).eqls([Infinity, -Infinity]); + expect(f1.stateValues.globalMaximum).eqls([]); + expect(f1.stateValues.globalSupremum).eqls([-Infinity, Infinity]); + expect(f2.stateValues.globalMinimum).eqls([]); + expect(f2.stateValues.globalInfimum).eqls([-Infinity, -Infinity]); + expect(f2.stateValues.globalMaximum).eqls([]); + expect(f2.stateValues.globalSupremum).eqls([Infinity, Infinity]); + expect(f3.stateValues.globalMinimum).eqls([]); + expect(f3.stateValues.globalInfimum).eqls([-9, 7.5]); + expect(f3.stateValues.globalMaximum).eqls([]); + expect(f3.stateValues.globalSupremum).eqls([-10, 8]); + expect(f4.stateValues.globalMinimum).eqls([3, 1.5]); + expect(f4.stateValues.globalInfimum).eqls([3, 1.5]); + expect(f4.stateValues.globalMaximum).eqls([-7, 6.5]); + expect(f4.stateValues.globalSupremum).eqls([-7, 6.5]); + expect(f5.stateValues.globalMinimum).eqls([10, -2]); + expect(f5.stateValues.globalInfimum).eqls([10, -2]); + expect(f5.stateValues.globalMaximum).eqls([]); + expect(f5.stateValues.globalSupremum).eqls([9, -1.5]); + expect(f6.stateValues.globalMinimum).eqls([]); + expect(f6.stateValues.globalInfimum).eqls([-10, -6]); + expect(f6.stateValues.globalMaximum).eqls([]); + expect(f6.stateValues.globalSupremum).eqls([-9, -5.5]); + expect(f7.stateValues.globalMinimum).eqls([-7, -4.5]); + expect(f7.stateValues.globalInfimum).eqls([-7, -4.5]); + expect(f7.stateValues.globalMaximum).eqls([3, 0.5]); + expect(f7.stateValues.globalSupremum).eqls([3, 0.5]); + expect(f8.stateValues.globalMinimum).eqls([]); + expect(f8.stateValues.globalInfimum).eqls([9, 3.5]); + expect(f8.stateValues.globalMaximum).eqls([10, 4]); + expect(f8.stateValues.globalSupremum).eqls([10, 4]); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/functioniterates.test.ts b/packages/doenetml-worker/src/test/tagSpecific/functioniterates.test.ts new file mode 100644 index 000000000..20c9c7edd --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/functioniterates.test.ts @@ -0,0 +1,482 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { cleanLatex } from "../utils/math"; +import { updateMathInputValue } from "../utils/actions"; +import me from "math-expressions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +describe("FunctionIterates tag tests", async () => { + // TODO: test forceNumeric and forceSymbolic? + + it("1D user-defined function", async () => { + let core = await createTestCore({ + doenetML: ` +

Choose variable for function: . + Let f($x) = . + Let u = . Let n= + Then

+
    + + + + +
+ +

$fformula$fis.iterates{name="iterates"}

+ + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/l1"].stateValues.text).eq("f¹(u) = 3 a v"); + expect(stateVariables["/l2"].stateValues.text).eq("f²(u) = 3 v a²"); + expect(stateVariables["/l3"].stateValues.text).eq("f³(u) = 3 v a³"); + + // change function, numIterates, and initial + await updateMathInputValue({ + latex: "bx^2", + componentName: "/fformula", + core, + }); + await updateMathInputValue({ latex: "4", componentName: "/n", core }); + await updateMathInputValue({ latex: "w", componentName: "/u", core }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/l1"].stateValues.text).eq("f¹(u) = b w²"); + expect(stateVariables["/l2"].stateValues.text).eq("f²(u) = b³ w⁴"); + expect(stateVariables["/l3"].stateValues.text).eq("f³(u) = b⁷ w⁸"); + expect(stateVariables["/l4"].stateValues.text).eq("f⁴(u) = b¹⁵ w¹⁶"); + + // change variable + await updateMathInputValue({ latex: "y", componentName: "/x", core }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/l1"].stateValues.text).eq("f¹(u) = b x²"); + expect(stateVariables["/l2"].stateValues.text).eq("f²(u) = b x²"); + expect(stateVariables["/l3"].stateValues.text).eq("f³(u) = b x²"); + expect(stateVariables["/l4"].stateValues.text).eq("f⁴(u) = b x²"); + + // change function to match variable + await updateMathInputValue({ + latex: "y+q", + componentName: "/fformula", + core, + }); + await updateMathInputValue({ latex: "5", componentName: "/n", core }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/l1"].stateValues.text).eq("f¹(u) = q + w"); + expect(stateVariables["/l2"].stateValues.text).eq("f²(u) = 2 q + w"); + expect(stateVariables["/l3"].stateValues.text).eq("f³(u) = 3 q + w"); + expect(stateVariables["/l4"].stateValues.text).eq("f⁴(u) = 4 q + w"); + expect(stateVariables["/l5"].stateValues.text).eq("f⁵(u) = 5 q + w"); + }); + + it("1D user-defined numerical function", async () => { + let core = await createTestCore({ + doenetML: ` +

Choose variable for function: . + Let f($x) = . + Let u = . Let n= + Then

+
    + + + + +
+ +

$fformula$fis.iterates{name="iterates"}

+ + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/l1"].stateValues.text).eq("f¹(u) = 6"); + expect(stateVariables["/l2"].stateValues.text).eq("f²(u) = 18"); + expect(stateVariables["/l3"].stateValues.text).eq("f³(u) = 54"); + + // change function, numIterates, and initial + await updateMathInputValue({ + latex: "2x^2", + componentName: "/fformula", + core, + }); + await updateMathInputValue({ latex: "4", componentName: "/n", core }); + await updateMathInputValue({ latex: "1/4", componentName: "/u", core }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/l1"].stateValues.text).eq("f¹(u) = 0.125"); + expect(stateVariables["/l2"].stateValues.text).eq("f²(u) = 0.03125"); + expect(stateVariables["/l3"].stateValues.text).eq( + "f³(u) = 0.001953125", + ); + expect(stateVariables["/l4"].stateValues.text).eq( + "f⁴(u) = 0.000007629394531", + ); + + // change variable + await updateMathInputValue({ latex: "y", componentName: "/x", core }); + + stateVariables = await returnAllStateVariables(core); + + // Ideally wouldn't have spaces in N a N, but get it from + // parsing the latex of the `` and converting to text + expect(stateVariables["/l1"].stateValues.text).eq("f¹(u) = N a N"); + expect(stateVariables["/l2"].stateValues.text).eq("f²(u) = N a N"); + expect(stateVariables["/l3"].stateValues.text).eq("f³(u) = N a N"); + expect(stateVariables["/l4"].stateValues.text).eq("f⁴(u) = N a N"); + + // change function to match variable + await updateMathInputValue({ + latex: "y+5", + componentName: "/fformula", + core, + }); + await updateMathInputValue({ latex: "5", componentName: "/n", core }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/l1"].stateValues.text).eq("f¹(u) = 5.25"); + expect(stateVariables["/l2"].stateValues.text).eq("f²(u) = 10.25"); + expect(stateVariables["/l3"].stateValues.text).eq("f³(u) = 15.25"); + expect(stateVariables["/l4"].stateValues.text).eq("f⁴(u) = 20.25"); + expect(stateVariables["/l5"].stateValues.text).eq("f⁵(u) = 25.25"); + }); + + async function test_2d_linear(core) { + async function checkIterates({ a, b, c, d, u1, u2, n }) { + let stateVariables = await returnAllStateVariables(core); + + let A = me.math.matrix([ + [a, b], + [c, d], + ]); + let x = me.math.matrix([[u1], [u2]]); + + let iterNames = stateVariables["/iterates"].replacements!.map( + (x) => x.componentName, + ); + + for (let i = 0; i < n; i++) { + x = me.math.multiply(A, x); + let x1 = me.math.subset(x, me.math.index(0, 0)); + let x2 = me.math.subset(x, me.math.index(1, 0)); + expect( + stateVariables[iterNames[i]].stateValues.value.tree, + ).eqls(["vector", x1, x2]); + } + } + + await checkIterates({ a: 3, b: -2, c: 1, d: 4, u1: 2, u2: 1, n: 3 }); + + // change values + await updateMathInputValue({ latex: "q", componentName: "/x", core }); + await updateMathInputValue({ latex: "r", componentName: "/y", core }); + await updateMathInputValue({ latex: "-4", componentName: "/a", core }); + await updateMathInputValue({ latex: "7", componentName: "/b", core }); + await updateMathInputValue({ latex: "6", componentName: "/c", core }); + await updateMathInputValue({ latex: "-1", componentName: "/d", core }); + await updateMathInputValue({ + latex: "(-8,9)", + componentName: "/u", + core, + }); + await updateMathInputValue({ latex: "5", componentName: "/n", core }); + + await checkIterates({ a: -4, b: 7, c: 6, d: -1, u1: -8, u2: 9, n: 5 }); + } + + it("2D linear function", async () => { + let core = await createTestCore({ + doenetML: ` +

variables: and . + a = , b = , c = , d = . + f($x, $y) = ($a$x+$b$y, $c$x+$d$y) + u = n=

+ + +

Iterates: $fis.iterates{name="iterates"}

+ + `, + }); + + await test_2d_linear(core); + }); + + it("2D linear function, with alt vectors", async () => { + let core = await createTestCore({ + doenetML: ` +

variables: and . + a = , b = , c = , d = . + f($x, $y) = ⟨$a$x+$b$y, $c$x+$d$y⟩ + u = n=

+ + +

Iterates: $fis.iterates{name="iterates"}

+ + `, + }); + await test_2d_linear(core); + }); + + it("warning for scalar function of two variables", async () => { + let core = await createTestCore({ + doenetML: ` + f(x, y) = x+y + + +

Iterates: $fis.iterates

+ + `, + }); + + let errorWarnings = core.errorWarnings; + + expect(errorWarnings.errors.length).eq(0); + expect(errorWarnings.warnings.length).eq(1); + + expect(errorWarnings.warnings[0].message).contain( + "Function iterates are possible only if the number of inputs of the function is equal to the number of outputs. This function has 2 inputs and 1 output", + ); + expect(errorWarnings.warnings[0].level).eq(1); + expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(4); + expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(3); + expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(4); + expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(84); + }); + + it("change dimensions", async () => { + let core = await createTestCore({ + doenetML: ` +

variables: . + f($vars) = . + u =

+ +

Iterates: $fis.iterates{name="iterates"}

+ + +

$vars$fformula

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let iterNames = stateVariables["/iterates"].replacements!.map( + (x) => x.componentName, + ); + + expect(stateVariables["/fis"].stateValues.numDimensions).eq(2); + expect(cleanLatex(stateVariables[iterNames[0]].stateValues.latex)).eq( + `(2,3)`, + ); + expect(cleanLatex(stateVariables[iterNames[1]].stateValues.latex)).eq( + `(6,5)`, + ); + expect(cleanLatex(stateVariables[iterNames[2]].stateValues.latex)).eq( + `(30,11)`, + ); + + await updateMathInputValue({ + latex: "(xy, x+yz, x-z)", + componentName: "/fformula", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + iterNames = stateVariables["/iterates"].replacements!.map( + (x) => x.componentName, + ); + + expect(stateVariables["/fis"].stateValues.numDimensions).eq(0); + expect(cleanLatex(stateVariables[iterNames[0]].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables[iterNames[1]].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables[iterNames[2]].stateValues.latex)).eq( + "\uff3f", + ); + + // add variable to function + await updateMathInputValue({ + latex: "x, y, z", + componentName: "/vars", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + iterNames = stateVariables["/iterates"].replacements!.map( + (x) => x.componentName, + ); + + expect(stateVariables["/fis"].stateValues.numDimensions).eq(3); + expect(cleanLatex(stateVariables[iterNames[0]].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables[iterNames[1]].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables[iterNames[2]].stateValues.latex)).eq( + "\uff3f", + ); + + // add component to initial condition + await updateMathInputValue({ + latex: "(2,1,-4)", + componentName: "/u", + core, + }); + stateVariables = await returnAllStateVariables(core); + + iterNames = stateVariables["/iterates"].replacements!.map( + (x) => x.componentName, + ); + expect(stateVariables["/fis"].stateValues.numDimensions).eq(3); + expect(cleanLatex(stateVariables[iterNames[0]].stateValues.latex)).eq( + `(2,-2,6)`, + ); + expect(cleanLatex(stateVariables[iterNames[1]].stateValues.latex)).eq( + `(-4,-10,-4)`, + ); + expect(cleanLatex(stateVariables[iterNames[2]].stateValues.latex)).eq( + `(40,36,0)`, + ); + }); + + it("change dimensions, numerical", async () => { + let core = await createTestCore({ + doenetML: ` +

variables: . + f($vars) = . + u =

+ +

Iterates: $fis.iterates{name="iterates"}

+ +

$vars$fformula

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let iterNames = stateVariables["/iterates"].replacements!.map( + (x) => x.componentName, + ); + + expect(stateVariables["/fis"].stateValues.numDimensions).eq(2); + expect(cleanLatex(stateVariables[iterNames[0]].stateValues.latex)).eq( + `(2,3)`, + ); + expect(cleanLatex(stateVariables[iterNames[1]].stateValues.latex)).eq( + `(6,5)`, + ); + expect(cleanLatex(stateVariables[iterNames[2]].stateValues.latex)).eq( + `(30,11)`, + ); + + // non-numeric initial condition + await updateMathInputValue({ + latex: "(2,1a)", + componentName: "/u", + core, + }); + stateVariables = await returnAllStateVariables(core); + + iterNames = stateVariables["/iterates"].replacements!.map( + (x) => x.componentName, + ); + + expect(stateVariables["/fis"].stateValues.numDimensions).eq(2); + + expect(cleanLatex(stateVariables[iterNames[0]].stateValues.latex)).eq( + `(NaN,NaN)`, + ); + expect(cleanLatex(stateVariables[iterNames[1]].stateValues.latex)).eq( + `(NaN,NaN)`, + ); + expect(cleanLatex(stateVariables[iterNames[2]].stateValues.latex)).eq( + `(NaN,NaN)`, + ); + + // add component to function + await updateMathInputValue({ + latex: "(2,1)", + componentName: "/u", + core, + }); + await updateMathInputValue({ + latex: "(xy, x+yz, x-z)", + componentName: "/fformula", + core, + }); + stateVariables = await returnAllStateVariables(core); + + iterNames = stateVariables["/iterates"].replacements!.map( + (x) => x.componentName, + ); + + expect(stateVariables["/fis"].stateValues.numDimensions).eq(0); + expect(cleanLatex(stateVariables[iterNames[0]].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables[iterNames[1]].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables[iterNames[2]].stateValues.latex)).eq( + "\uff3f", + ); + + // add variable to function + await updateMathInputValue({ + latex: "x, y, z", + componentName: "/vars", + core, + }); + stateVariables = await returnAllStateVariables(core); + + iterNames = stateVariables["/iterates"].replacements!.map( + (x) => x.componentName, + ); + + expect(stateVariables["/fis"].stateValues.numDimensions).eq(3); + expect(cleanLatex(stateVariables[iterNames[0]].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables[iterNames[1]].stateValues.latex)).eq( + "\uff3f", + ); + expect(cleanLatex(stateVariables[iterNames[2]].stateValues.latex)).eq( + "\uff3f", + ); + + // add component to initial condition + await updateMathInputValue({ + latex: "(2,1,-4)", + componentName: "/u", + core, + }); + stateVariables = await returnAllStateVariables(core); + + iterNames = stateVariables["/iterates"].replacements!.map( + (x) => x.componentName, + ); + + expect(stateVariables["/fis"].stateValues.numDimensions).eq(3); + expect(cleanLatex(stateVariables[iterNames[0]].stateValues.latex)).eq( + `(2,-2,6)`, + ); + expect(cleanLatex(stateVariables[iterNames[1]].stateValues.latex)).eq( + `(-4,-10,-4)`, + ); + expect(cleanLatex(stateVariables[iterNames[2]].stateValues.latex)).eq( + `(40,36,0)`, + ); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/graph.test.ts b/packages/doenetml-worker/src/test/tagSpecific/graph.test.ts new file mode 100644 index 000000000..c7733b598 --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/graph.test.ts @@ -0,0 +1,1054 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { + updateBooleanInputValue, + updateMathInputValue, + updateTextInputValue, +} from "../utils/actions"; +import { widthsBySize } from "@doenet/utils"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +describe("Graph tag tests", async () => { + it("functions adapted to curves in graph", async () => { + let core = await createTestCore({ + doenetML: ` + + x^2 + t^3 + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + let curve1Name = stateVariables["/g"].activeChildren[0].componentName; + let curve2Name = stateVariables["/g"].activeChildren[1].componentName; + + let f1 = stateVariables[curve1Name].stateValues.fs[0]; + let f2 = stateVariables[curve2Name].stateValues.fs[0]; + + expect(f1(-2)).eq(4); + expect(f1(3)).eq(9); + expect(f2(-2)).eq(-8); + expect(f2(3)).eq(27); + expect(stateVariables[curve1Name].componentType).eq("curve"); + expect(stateVariables[curve2Name].componentType).eq("curve"); + expect(stateVariables[curve1Name].stateValues.label).eq(""); + expect(stateVariables[curve2Name].stateValues.label).eq("g"); + expect(stateVariables[curve1Name].stateValues.styleNumber).eq(1); + expect(stateVariables[curve2Name].stateValues.styleNumber).eq(2); + }); + + it("labels and positioning", async () => { + let core = await createTestCore({ + doenetML: ` + a + + + $xlabel$ylabel + + + + + xlabel: + position: + + left + right + + + + ylabel: + position: + + top + bottom + + + alignment: + + left + right + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/g"].stateValues.xlabel).eq("x"); + expect(stateVariables["/g"].stateValues.xlabelPosition).eq("right"); + expect(stateVariables["/g"].stateValues.ylabel).eq("y"); + expect(stateVariables["/g"].stateValues.ylabelPosition).eq("top"); + expect(stateVariables["/g"].stateValues.ylabelAlignment).eq("left"); + + await updateTextInputValue({ + text: "hello", + componentName: "/xlabel", + core, + }); + await updateTextInputValue({ + text: "bye", + componentName: "/ylabel", + core, + }); + + await core.requestAction({ + componentName: "/xlabelpos", + actionName: "updateSelectedIndices", + args: { selectedIndices: [1] }, + event: null, + }); + await core.requestAction({ + componentName: "/ylabelpos", + actionName: "updateSelectedIndices", + args: { selectedIndices: [2] }, + event: null, + }); + await core.requestAction({ + componentName: "/ylabelalign", + actionName: "updateSelectedIndices", + args: { selectedIndices: [2] }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/g"].stateValues.xlabel).eq("hello"); + expect(stateVariables["/g"].stateValues.xlabelPosition).eq("left"); + expect(stateVariables["/g"].stateValues.ylabel).eq("bye"); + expect(stateVariables["/g"].stateValues.ylabelPosition).eq("bottom"); + expect(stateVariables["/g"].stateValues.ylabelAlignment).eq("right"); + }); + + it("change essential xlabel and ylabel", async () => { + let core = await createTestCore({ + doenetML: ` + +

+

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/g"].stateValues.xlabel).eq(""); + expect(stateVariables["/g"].stateValues.ylabel).eq(""); + + await core.requestAction({ + componentName: "/uvx", + actionName: "updateValue", + args: {}, + event: null, + }); + await core.requestAction({ + componentName: "/uvy", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/g"].stateValues.xlabel).eq("s"); + expect(stateVariables["/g"].stateValues.ylabel).eq("t"); + }); + + it("identical axis scales, with given aspect ratio", async () => { + type AxisLimits = { + xmin: number; + xmax: number; + ymin: number; + ymax: number; + }; + + async function checkLimits( + core: any, + { xmin, xmax, ymin, ymax }: AxisLimits, + ) { + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/g"].stateValues.xmin).eq(xmin); + expect(stateVariables["/g"].stateValues.xmax).eq(xmax); + expect(stateVariables["/g"].stateValues.ymin).eq(ymin); + expect(stateVariables["/g"].stateValues.ymax).eq(ymax); + } + + async function test_case({ + specified_limits, + ratio1, + ratio2, + ratio05, + }: { + specified_limits: string; + ratio1: AxisLimits; + ratio2: AxisLimits; + ratio05: AxisLimits; + }) { + const doenetML = ` +

Aspect ratio:

+ + `; + + const core = await createTestCore({ doenetML }); + + await checkLimits(core, ratio1); + + await updateMathInputValue({ + latex: "2", + componentName: "/aspectRatio", + core, + }); + await checkLimits(core, ratio2); + + await updateMathInputValue({ + latex: "1/2", + componentName: "/aspectRatio", + core, + }); + await checkLimits(core, ratio05); + } + + let cases = [ + { + specified_limits: ``, + ratio1: { xmin: -10, xmax: 10, ymin: -10, ymax: 10 }, + ratio2: { xmin: -10, xmax: 10, ymin: -5, ymax: 5 }, + ratio05: { xmin: -10, xmax: 10, ymin: -20, ymax: 20 }, + }, + { + specified_limits: `xmin="-5"`, + ratio1: { xmin: -5, xmax: 15, ymin: -10, ymax: 10 }, + ratio2: { xmin: -5, xmax: 15, ymin: -5, ymax: 5 }, + ratio05: { xmin: -5, xmax: 15, ymin: -20, ymax: 20 }, + }, + { + specified_limits: `xmax="5"`, + ratio1: { xmin: -15, xmax: 5, ymin: -10, ymax: 10 }, + ratio2: { xmin: -15, xmax: 5, ymin: -5, ymax: 5 }, + ratio05: { xmin: -15, xmax: 5, ymin: -20, ymax: 20 }, + }, + { + specified_limits: `ymin="-5"`, + ratio1: { xmin: -10, xmax: 10, ymin: -5, ymax: 15 }, + ratio2: { xmin: -10, xmax: 10, ymin: -5, ymax: 5 }, + ratio05: { xmin: -10, xmax: 10, ymin: -5, ymax: 35 }, + }, + { + specified_limits: `ymax="5"`, + ratio1: { xmin: -10, xmax: 10, ymin: -15, ymax: 5 }, + ratio2: { xmin: -10, xmax: 10, ymin: -5, ymax: 5 }, + ratio05: { xmin: -10, xmax: 10, ymin: -35, ymax: 5 }, + }, + { + specified_limits: `xmin="-20" xmax="40"`, + ratio1: { xmin: -20, xmax: 40, ymin: -30, ymax: 30 }, + ratio2: { xmin: -20, xmax: 40, ymin: -15, ymax: 15 }, + ratio05: { xmin: -20, xmax: 40, ymin: -60, ymax: 60 }, + }, + { + specified_limits: `ymin="-20" ymax="40"`, + ratio1: { xmin: -30, xmax: 30, ymin: -20, ymax: 40 }, + ratio2: { xmin: -60, xmax: 60, ymin: -20, ymax: 40 }, + ratio05: { xmin: -15, xmax: 15, ymin: -20, ymax: 40 }, + }, + { + // all specified + specified_limits: `xmin="-50" xmax="30" ymin="-20" ymax="40"`, + ratio1: { xmin: -50, xmax: 30, ymin: -20, ymax: 60 }, + ratio2: { xmin: -50, xmax: 70, ymin: -20, ymax: 40 }, + ratio05: { xmin: -50, xmax: 30, ymin: -20, ymax: 140 }, + }, + { + // leave out xmin + specified_limits: `xmax="30" ymin="-20" ymax="40"`, + ratio1: { xmin: -30, xmax: 30, ymin: -20, ymax: 40 }, + ratio2: { xmin: -90, xmax: 30, ymin: -20, ymax: 40 }, + ratio05: { xmin: 0, xmax: 30, ymin: -20, ymax: 40 }, + }, + { + // leave out xmax + specified_limits: `xmin="-30" ymin="-20" ymax="40"`, + ratio1: { xmin: -30, xmax: 30, ymin: -20, ymax: 40 }, + ratio2: { xmin: -30, xmax: 90, ymin: -20, ymax: 40 }, + ratio05: { xmin: -30, xmax: 0, ymin: -20, ymax: 40 }, + }, + { + // leave out ymin + specified_limits: `xmin="-50" xmax="30" ymax="40"`, + ratio1: { xmin: -50, xmax: 30, ymin: -40, ymax: 40 }, + ratio2: { xmin: -50, xmax: 30, ymin: 0, ymax: 40 }, + ratio05: { xmin: -50, xmax: 30, ymin: -120, ymax: 40 }, + }, + { + // leave out ymax + specified_limits: `xmin="-50" xmax="30" ymin="-40"`, + ratio1: { xmin: -50, xmax: 30, ymin: -40, ymax: 40 }, + ratio2: { xmin: -50, xmax: 30, ymin: -40, ymax: 0 }, + ratio05: { xmin: -50, xmax: 30, ymin: -40, ymax: 120 }, + }, + ]; + + for (let c of cases) { + await test_case(c); + } + }); + + it("identical axis scales, without given aspect ratio", async () => { + let core = await createTestCore({ + doenetML: ` + + +

xmin: $g.xmin{assignNames="xmin"}

+

xmax: $g.xmax{assignNames="xmax"}

+

ymin: $g.ymin{assignNames="ymin"}

+

ymax: $g.ymax{assignNames="ymax"}

+ +

Change xmin:

+

Change xmax:

+

Change ymin:

+

Change ymax:

+ + `, + }); + + async function checkLimits(xmin, xmax, ymin, ymax) { + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/g"].stateValues.xmin).eq(xmin); + expect(stateVariables["/g"].stateValues.xmax).eq(xmax); + expect(stateVariables["/g"].stateValues.ymin).eq(ymin); + expect(stateVariables["/g"].stateValues.ymax).eq(ymax); + + expect(stateVariables["/g"].stateValues.aspectRatio).eq( + (xmax - xmin) / (ymax - ymin), + ); + } + + await checkLimits(-10, 10, -10, 10); + + // set xmin to -5 + await updateMathInputValue({ + latex: "-5", + componentName: "/xminInput", + core, + }); + await checkLimits(-5, 10, -10, 10); + + // set ymax to 0 + await updateMathInputValue({ + latex: "0", + componentName: "/ymaxInput", + core, + }); + await checkLimits(-5, 10, -10, 0); + }); + + it("show grid", async () => { + let core = await createTestCore({ + doenetML: ` + + +

Graph 1 has grid: $g1.grid{assignNames="sg1"}

+ + +

Graph 2 has grid: $g2.grid{assignNames="sg2"}

+ + +

Graph 3 has grid: $g3.grid{assignNames="sg3"}

+ + +

Graph 4 has grid: $g4.grid{assignNames="sg4"}

+ + +

Graph 5 has grid: $g5.grid{assignNames="sg5"}

+ + +

Show grid:

+ +

Graph 6 has grid: $g6.grid{assignNames="sg6"}

+ + +

Show grid:

+ +

Graph 7 has grid: $g7.grid{assignNames="sg7"}

+ + `, + }); + + // not sure what to test as don't know how to check renderer... + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/sg1"].stateValues.value).eq("none"); + expect(stateVariables["/sg2"].stateValues.value).eq("none"); + expect(stateVariables["/sg3"].stateValues.value).eq("medium"); + expect(stateVariables["/sg4"].stateValues.value).eq("medium"); + expect(stateVariables["/sg5"].stateValues.value).eq("dense"); + expect(stateVariables["/sg6"].stateValues.value).eq("none"); + expect(stateVariables["/sg7"].stateValues.value).eq("none"); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/bi", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/sg6"].stateValues.value).eq("medium"); + + await updateTextInputValue({ + text: "true", + componentName: "/ti", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/sg7"].stateValues.value).eq("medium"); + + await updateTextInputValue({ + text: "false", + componentName: "/ti", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/sg7"].stateValues.value).eq("none"); + + await updateTextInputValue({ + text: "dense", + componentName: "/ti", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/sg7"].stateValues.value).eq("dense"); + + await updateTextInputValue({ + text: "hello", + componentName: "/ti", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/sg7"].stateValues.value).eq("none"); + + await updateTextInputValue({ + text: "medium", + componentName: "/ti", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/sg7"].stateValues.value).eq("medium"); + + await updateTextInputValue({ + text: "none", + componentName: "/ti", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/sg7"].stateValues.value).eq("none"); + }); + + it("fixed grids", async () => { + let core = await createTestCore({ + doenetML: ` + + +

Graph 1 has grid: $g1.grid{assignNames="sg1"}

+ +

grid x:

+

grid y:

+ +

Graph 2 has grid: $g2.grid{assignNames="sg2"}

+ +

grid x: $g3x

+

grid y: $g3y

+ +

Graph 3 has grid: $g3.grid{assignNames="sg3"}

+ +

grid x:

+

grid y:

+ +

Graph 4 has grid: $g4.grid{assignNames="sg4"}

+ +

grid x: $g5x

+

grid y: $g5y

+ +

Graph 5 has grid: $g5.grid{assignNames="sg5"}

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/sg1"].stateValues.numbers).eqls([ + 1, + Math.PI / 2, + ]); + expect(stateVariables["/sg2"].stateValues.value).eq("none"); + expect(stateVariables["/sg3"].stateValues.value).eq("none"); + expect(stateVariables["/sg4"].stateValues.numbers).eqls([2, 3]); + expect(stateVariables["/sg5"].stateValues.numbers).eqls([2, 3]); + + await updateMathInputValue({ latex: "3", componentName: "/g2x", core }); + await updateMathInputValue({ + latex: "1.5", + componentName: "/g2y", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/sg2"].stateValues.numbers).eqls([3, 1.5]); + + await updateMathInputValue({ latex: "3", componentName: "/g3x", core }); + await updateMathInputValue({ + latex: "1.5", + componentName: "/g3y", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/sg3"].stateValues.numbers).eqls([3, 1.5]); + + await updateMathInputValue({ latex: "3", componentName: "/g4x", core }); + await updateMathInputValue({ + latex: "1.5", + componentName: "/g4y", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/sg4"].stateValues.numbers).eqls([ + 3 * 2, + 1.5 * 3, + ]); + + await updateMathInputValue({ latex: "3", componentName: "/g5x", core }); + await updateMathInputValue({ + latex: "1.5", + componentName: "/g5y", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/sg5"].stateValues.numbers).eqls([ + 3 * 2, + 1.5 * 3, + ]); + + await updateMathInputValue({ + latex: "3e/2", + componentName: "/g2x", + core, + }); + await updateMathInputValue({ + latex: "1.5\\pi", + componentName: "/g2y", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/sg2"].stateValues.numbers).eqls([ + (3 * Math.E) / 2, + 1.5 * Math.PI, + ]); + + await updateMathInputValue({ + latex: "3e/2", + componentName: "/g3x", + core, + }); + await updateMathInputValue({ + latex: "1.5\\pi", + componentName: "/g3y", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/sg3"].stateValues.numbers).eqls([ + (3 * Math.E) / 2, + 1.5 * Math.PI, + ]); + + await updateMathInputValue({ + latex: "3\\pi/5", + componentName: "/g4x", + core, + }); + await updateMathInputValue({ + latex: "1.5e/6", + componentName: "/g4y", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/sg4"].stateValues.numbers).eqls([ + ((3 * Math.PI) / 5) * 2, + ((1.5 * Math.E) / 6) * 3, + ]); + + await updateMathInputValue({ + latex: "3\\pi/5", + componentName: "/g5x", + core, + }); + await updateMathInputValue({ + latex: "1.5e/6", + componentName: "/g5y", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/sg5"].stateValues.numbers).eqls([ + ((3 * Math.PI) / 5) * 2, + ((1.5 * Math.E) / 6) * 3, + ]); + }); + + // check for bug in placeholder adapter + it("graph with label as submitted response, createComponentOfType specified", async () => { + let core = await createTestCore({ + doenetML: ` + + $(x.submittedResponse{ createComponentOfType='math'}) + y + + + x + `, + }); + + // not sure what to test as don't know how to check renderer... + // but main thing is that don't have an error + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/graph1"].stateValues.xlabel).eq("\\(\uff3f\\)"); + + let mathinputName = + stateVariables["/x"].stateValues.inputChildren[0].componentName; + + await updateMathInputValue({ + latex: "x", + componentName: mathinputName, + core, + }); + await core.requestAction({ + componentName: "/x", + actionName: "submitAnswer", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/graph1"].stateValues.xlabel).eq("\\(x\\)"); + }); + + it("display tick labels", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + `, + }); + + // not sure what to test as don't know how to check renderer... + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/g"].stateValues.displayXAxisTickLabels).eq( + false, + ); + expect(stateVariables["/g"].stateValues.displayYAxisTickLabels).eq( + true, + ); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/b1", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/g"].stateValues.displayXAxisTickLabels).eq( + true, + ); + expect(stateVariables["/g"].stateValues.displayYAxisTickLabels).eq( + true, + ); + + await updateBooleanInputValue({ + boolean: false, + componentName: "/b2", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/g"].stateValues.displayXAxisTickLabels).eq( + true, + ); + expect(stateVariables["/g"].stateValues.displayYAxisTickLabels).eq( + false, + ); + + await updateBooleanInputValue({ + boolean: false, + componentName: "/b1", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/g"].stateValues.displayXAxisTickLabels).eq( + false, + ); + expect(stateVariables["/g"].stateValues.displayYAxisTickLabels).eq( + false, + ); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/b2", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/g"].stateValues.displayXAxisTickLabels).eq( + false, + ); + expect(stateVariables["/g"].stateValues.displayYAxisTickLabels).eq( + true, + ); + }); + + it("graph sizes", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + `, + }); + + let expectedSizes = { + g: "medium", + gtiny: "tiny", + gsmall: "small", + gmedium: "medium", + glarge: "large", + gfull: "full", + ginvalid: "medium", + ga10: "tiny", + ga100: "tiny", + ga200: "small", + ga300: "small", + ga400: "medium", + ga500: "medium", + ga600: "large", + ga700: "large", + ga800: "full", + ga900: "full", + ga10000: "full", + gp1: "tiny", + gp10: "tiny", + gp20: "small", + gp30: "small", + gp40: "small", + gp50: "medium", + gp60: "medium", + gp70: "large", + gp80: "large", + gp90: "full", + gp100: "full", + gp1000: "full", + gbadwidth: "medium", + }; + + let stateVariables = await returnAllStateVariables(core); + for (let name in expectedSizes) { + expect(stateVariables["/" + name].stateValues.size).eq( + expectedSizes[name], + ); + expect(stateVariables["/" + name].stateValues.width.size).eq( + widthsBySize[expectedSizes[name]], + ); + } + }); + + it("horizontal align", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/g"].stateValues.horizontalAlign).eq("center"); + expect(stateVariables["/gleft"].stateValues.horizontalAlign).eq("left"); + expect(stateVariables["/gright"].stateValues.horizontalAlign).eq( + "right", + ); + expect(stateVariables["/gcenter"].stateValues.horizontalAlign).eq( + "center", + ); + expect(stateVariables["/ginvalid"].stateValues.horizontalAlign).eq( + "center", + ); + }); + + it("displayMode", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/g"].stateValues.displayMode).eq("block"); + expect(stateVariables["/ginline"].stateValues.displayMode).eq("inline"); + expect(stateVariables["/gblock"].stateValues.displayMode).eq("block"); + expect(stateVariables["/ginvalid"].stateValues.displayMode).eq("block"); + }); + + it("display axes", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + `, + }); + + // not sure what to test as don't know how to check renderer... + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/g"].stateValues.displayXAxis).eq(false); + expect(stateVariables["/g"].stateValues.displayYAxis).eq(true); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/b1", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/g"].stateValues.displayXAxis).eq(true); + expect(stateVariables["/g"].stateValues.displayYAxis).eq(true); + + await updateBooleanInputValue({ + boolean: false, + componentName: "/b2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/g"].stateValues.displayXAxis).eq(true); + expect(stateVariables["/g"].stateValues.displayYAxis).eq(false); + + await updateBooleanInputValue({ + boolean: false, + componentName: "/b1", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/g"].stateValues.displayXAxis).eq(false); + expect(stateVariables["/g"].stateValues.displayYAxis).eq(false); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/b2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/g"].stateValues.displayXAxis).eq(false); + expect(stateVariables["/g"].stateValues.displayYAxis).eq(true); + }); + + it("display navigation bar", async () => { + let core = await createTestCore({ + doenetML: ` + + + + `, + }); + + // not sure what to test as don't know how to check renderer... + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/g"].stateValues.showNavigation).eq(false); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/b", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/g"].stateValues.showNavigation).eq(true); + + await updateBooleanInputValue({ + boolean: false, + componentName: "/b", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/g"].stateValues.showNavigation).eq(false); + }); + + it("display digits and decimals, overwrite in copies", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + +

$g.xmin, $g.xmax, $g.ymin, $g.ymax

+ +

$gdg3.xmin, $gdg3.xmax, $gdg3.ymin, $gdg3.ymax

+

$gdg3a.xmin, $gdg3a.xmax, $gdg3a.ymin, $gdg3a.ymax

+

$gdg3b.xmin, $gdg3b.xmax, $gdg3b.ymin, $gdg3b.ymax

+

$g{displayDigits="5"}.xmin, $g{displayDigits="5"}.xmax, $g{displayDigits="5"}.ymin, $g{displayDigits="5"}.ymax

+

$gdc5{displayDigits="5"}.xmin, $gdc5{displayDigits="5"}.xmax, $gdc5{displayDigits="5"}.ymin, $gdc5{displayDigits="5"}.ymax

+ +

$gdc5.xmin, $gdc5.xmax, $gdc5.ymin, $gdc5.ymax

+

$gdc5a.xmin, $gdc5a.xmax, $gdc5a.ymin, $gdc5a.ymax

+

$gdc5b.xmin, $gdc5b.xmax, $gdc5b.ymin, $gdc5b.ymax

+

$g{displayDecimals="5"}.xmin, $g{displayDecimals="5"}.xmax, $g{displayDecimals="5"}.ymin, $g{displayDecimals="5"}.ymax

+

$gdg3{displayDecimals="5"}.xmin, $gdg3{displayDecimals="5"}.xmax, $gdg3{displayDecimals="5"}.ymin, $gdg3{displayDecimals="5"}.ymax

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p"].stateValues.text).eq( + "-45.03, 8.29, -5.58, 7.84", + ); + + expect(stateVariables["/pdg3"].stateValues.text).eq( + "-45.032, 8.2857, -5.5823, 7.8371", + ); + expect(stateVariables["/pdg3b"].stateValues.text).eq( + "-45.032, 8.2857, -5.5823, 7.8371", + ); + expect(stateVariables["/pdg3c"].stateValues.text).eq( + "-45.032, 8.2857, -5.5823, 7.8371", + ); + expect(stateVariables["/pdg3d"].stateValues.text).eq( + "-45.032, 8.2857, -5.5823, 7.8371", + ); + expect(stateVariables["/pdc5"].stateValues.text).eq( + "-45.03233, 8.28572, -5.58234, 7.8371", + ); + expect(stateVariables["/pdc5b"].stateValues.text).eq( + "-45.03233, 8.28572, -5.58234, 7.8371", + ); + expect(stateVariables["/pdc5c"].stateValues.text).eq( + "-45.03233, 8.28572, -5.58234, 7.8371", + ); + expect(stateVariables["/pdc5d"].stateValues.text).eq( + "-45.03233, 8.28572, -5.58234, 7.8371", + ); + }); + + it("pegboard", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + `, + }); + + // not sure what to test as don't know how to check renderer... + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_pegboard1"].stateValues.dx).eq(1); + expect(stateVariables["/_pegboard1"].stateValues.dy).eq(1); + expect(stateVariables["/_pegboard1"].stateValues.xoffset).eq(0); + expect(stateVariables["/_pegboard1"].stateValues.yoffset).eq(0); + expect(stateVariables["/_pegboard2"].stateValues.dx).eq(3); + expect(stateVariables["/_pegboard2"].stateValues.dy).eq(2); + expect(stateVariables["/_pegboard2"].stateValues.xoffset).eq(1); + expect(stateVariables["/_pegboard2"].stateValues.yoffset).eq(-1); + }); + + it("show border", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + `, + }); + + // not sure what to test as don't know how to check renderer... + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/_graph1"].stateValues.showBorder).eq(true); + expect(stateVariables["/_graph2"].stateValues.showBorder).eq(true); + expect(stateVariables["/_graph3"].stateValues.showBorder).eq(false); + }); + + it("graph inside graph renders children in parent graph", async () => { + let core = await createTestCore({ + doenetML: ` + + (4,-5) + + (6,9) + + + + + + + + + $g1 + + + `, + }); + + // Not sure what to test as the interesting part is the graph renderer + // The only new part from core is that the inner graph ignores its xmin, etc. attributes + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/g1inner"].stateValues.xmin).eq(-10); + expect(stateVariables["/g1inner"].stateValues.xmax).eq(10); + expect(stateVariables["/g1inner"].stateValues.ymin).eq(-10); + expect(stateVariables["/g1inner"].stateValues.ymax).eq(10); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/map.test.ts b/packages/doenetml-worker/src/test/tagSpecific/map.test.ts new file mode 100644 index 000000000..ceb78bf61 --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/map.test.ts @@ -0,0 +1,1859 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { + updateBooleanInputValue, + updateMathInputValue, +} from "../utils/actions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +describe("Map tag tests", async () => { + it("single map of maths", async () => { + let core = await createTestCore({ + doenetML: ` +

+ + + x + y + +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let replacements = stateVariables["/map1"].replacements!; + let mathr1Name = + stateVariables[replacements[0].componentName].replacements![0] + .componentName; + let mathr2Name = + stateVariables[replacements[1].componentName].replacements![0] + .componentName; + + expect(stateVariables["/p"].stateValues.text).eq( + "sin(2 x) + 1, sin(2 y) + 2", + ); + + expect(stateVariables[mathr1Name].stateValues.value.tree).eqls([ + "+", + ["apply", "sin", ["*", 2, "x"]], + 1, + ]); + expect(stateVariables[mathr2Name].stateValues.value.tree).eqls([ + "+", + ["apply", "sin", ["*", 2, "y"]], + 2, + ]); + }); + + it("single map of texts", async () => { + let core = await createTestCore({ + doenetML: ` +

+ + squirrelbat +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let replacements = stateVariables["/map1"].replacements!; + let textr1Name = + stateVariables[replacements[0].componentName].replacements![0] + .componentName; + let textr2Name = + stateVariables[replacements[1].componentName].replacements![0] + .componentName; + + expect(stateVariables["/p"].stateValues.text).eq( + "You are a squirrel! You are a bat! ", + ); + + expect(stateVariables[textr1Name].stateValues.value).eq( + "You are a squirrel!", + ); + + expect(stateVariables[textr2Name].stateValues.value).eq( + "You are a bat!", + ); + }); + + it("single map of sequence", async () => { + let core = await createTestCore({ + doenetML: ` +

+ + +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let replacements = stateVariables["/map1"].replacements!; + let mathrNames = replacements.map( + (x) => + stateVariables[x.componentName].replacements![0].componentName, + ); + + expect(stateVariables["/p"].stateValues.text).eq("1, 4, 9, 16, 25"); + expect(stateVariables[mathrNames[0]].stateValues.value.tree).eq(1); + expect(stateVariables[mathrNames[1]].stateValues.value.tree).eq(4); + expect(stateVariables[mathrNames[2]].stateValues.value.tree).eq(9); + expect(stateVariables[mathrNames[3]].stateValues.value.tree).eq(16); + expect(stateVariables[mathrNames[4]].stateValues.value.tree).eq(25); + }); + + it("triple parallel map", async () => { + let core = await createTestCore({ + doenetML: ` +

+ + + + +

+ `, + }); + + let options1 = [1, 2, 3, 4, 5]; + let options2 = [21, 22, 23]; + let options3 = [-5, -8, -11, -14, -17, -20]; + + let nValues = Math.min( + options1.length, + options2.length, + options3.length, + ); + + let values: number[][] = []; + let indices: number[][] = []; + + for (let i = 0; i < nValues; i++) { + values.push([options1[i], options2[i], options3[i]]); + indices.push([i + 1, i + 1, i + 1]); + } + + let pText = values + .map((v, i) => `( ${v.join(", ")} ): ( ${indices[i].join(", ")} )`) + .join(", "); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p"].stateValues.text).eq(pText); + + // Have warning that ignored extra iterates + let errorWarnings = core.errorWarnings; + expect(errorWarnings.errors.length).eq(0); + expect(errorWarnings.warnings.length).eq(1); + + expect(errorWarnings.warnings[0].message).contain( + " has parallel behavior but different numbers of iterates in sources. Extra iterates will be ignored", + ); + expect(errorWarnings.warnings[0].level).eq(1); + expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(2); + expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(17); + expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(7); + expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(10); + }); + + it("triple combination map", async () => { + let core = await createTestCore({ + doenetML: ` +

+ + + + +

+ `, + }); + + let options1 = [1, 2, 3]; + let options2 = [21, 23]; + let options3 = [-5, -8]; + let values: number[][] = []; + let indices: number[][] = []; + + for (let [i, l] of options1.entries()) { + for (let [j, m] of options2.entries()) { + for (let [k, n] of options3.entries()) { + values.push([l, m, n]); + indices.push([i + 1, j + 1, k + 1]); + } + } + } + + let pText = values + .map((v, i) => `( ${v.join(", ")} ): ( ${indices[i].join(", ")} )`) + .join(", "); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p"].stateValues.text).eq(pText); + }); + + it("map with invalid behavior", async () => { + let core = await createTestCore({ + doenetML: ` +

+ + 1 +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p"].stateValues.text).eq(""); + + let errorWarnings = core.errorWarnings; + + expect(errorWarnings.errors.length).eq(0); + expect(errorWarnings.warnings.length).eq(1); + + expect(errorWarnings.warnings[0].message).contain( + `Invalid map behavior: "bad"`, + ); + expect(errorWarnings.warnings[0].level).eq(1); + expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(2); + expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(17); + expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(5); + expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(10); + }); + + it("two nested maps", async () => { + let core = await createTestCore({ + doenetML: ` +

+ + -105 +

+ + `, + }); + + let options1 = [1, 2]; + let options2 = [-10, 5]; + let values1: number[] = []; + let values2: number[] = []; + + for (let [j, n] of options2.entries()) { + for (let [i, m] of options1.entries()) { + values1.push(m + n); + values2.push(i + 1 + 2 * (j + 1)); + } + } + + let pText = values1.map((v, i) => `${v} and ${values2[i]}`).join(", "); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p"].stateValues.text).eq(pText); + }); + + it("three nested maps with graphs and copied", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + $map1{name="mapCopy"} + `, + }); + + let options1 = [1, 2]; + let options2 = [-5, 5]; + let options3 = [-10, 5]; + + let point1sByGraph: number[][][] = []; + let point2sByGraph: number[][][] = []; + + for (let [k, n] of options3.entries()) { + point1sByGraph.push([]); + point2sByGraph.push([]); + for (let [j, m] of options2.entries()) { + for (let [i, l] of options1.entries()) { + point1sByGraph[k].push([l + n, m]); + point2sByGraph[k].push([i + 1 + 2 * (k + 1), j + 1]); + } + } + } + + let stateVariables = await returnAllStateVariables(core); + + function checkMap(mapName: string) { + let graphNames = stateVariables[mapName].replacements!.map( + (x) => + stateVariables[x.componentName].replacements![0] + .componentName, + ); + + for (let [graphInd, graphName] of graphNames.entries()) { + let point1NamesForGraph: string[] = []; + let point2NamesForGraph: string[] = []; + + let allPointNames = stateVariables[ + graphName + ].activeChildren.map((x) => x.componentName); + + expect(allPointNames.length).eq(8); + + for (let [pointInd, pointName] of allPointNames.entries()) { + if (pointInd % 2 === 0) { + point1NamesForGraph.push(pointName); + } else { + point2NamesForGraph.push(pointName); + } + } + + for (let [ind, val] of point1sByGraph[graphInd].entries()) { + let name = point1NamesForGraph[ind]; + expect( + stateVariables[name].stateValues.xs.map((x) => x.tree), + ).eqls(val); + } + for (let [ind, val] of point2sByGraph[graphInd].entries()) { + let name = point2NamesForGraph[ind]; + expect( + stateVariables[name].stateValues.xs.map((x) => x.tree), + ).eqls(val); + } + } + } + + await checkMap("/map1"); + await checkMap("/mapCopy"); + }); + + it("three nested maps with graphs and assignNames", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + + + + + `, + }); + + let options1 = [1, 2]; + let options2 = [-5, 5]; + let options3 = [-10, 5]; + + let pointsByMap: number[][][][] = []; + + for (let [k, n] of options3.entries()) { + pointsByMap.push([]); + for (let [j, m] of options2.entries()) { + pointsByMap[k].push([]); + for (let [i, l] of options1.entries()) { + pointsByMap[k][j].push([l + n, m]); + } + } + } + + let stateVariables = await returnAllStateVariables(core); + + expect( + stateVariables["/u/graph1"].stateValues.graphicalDescendants.length, + ).eq(4); + expect( + stateVariables["/v/graph1"].stateValues.graphicalDescendants.length, + ).eq(4); + + let assignedNames = ["/u", "/v"]; + + let cNames = ["/c8", "/c7", "/c6", "/c5", "/c4", "/c3", "/c2", "/c1"]; + + for (let [i1, name1] of assignedNames.entries()) { + for (let [i2, name2] of assignedNames.entries()) { + for (let [i3, name3] of assignedNames.entries()) { + let name = name1 + name2 + name3 + "/A"; + expect( + stateVariables[name].stateValues.xs.map((x) => x.tree), + ).eqls(pointsByMap[i1][i2][i3]); + + let cName = cNames.pop(); + + expect(stateVariables[cName!].stateValues.value.tree).eqls([ + "vector", + ...pointsByMap[i1][i2][i3], + ]); + } + } + } + }); + + it("combination map nested inside map with graphs", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + `, + }); + + let options1 = [1, 2]; + let options2 = [-5, 5]; + let options3 = [-10, 5]; + + let pointsByGraph: number[][][] = []; + + for (let [k, n] of options3.entries()) { + pointsByGraph.push([]); + for (let [i, l] of options1.entries()) { + for (let [j, m] of options2.entries()) { + pointsByGraph[k].push([l + n, m]); + } + } + } + + let stateVariables = await returnAllStateVariables(core); + + let graphNames = stateVariables["/map1"].replacements!.map( + (x) => + stateVariables[x.componentName].replacements![0].componentName, + ); + + for (let [graphInd, graphName] of graphNames.entries()) { + expect( + stateVariables[graphName].stateValues.graphicalDescendants + .length, + ).eq(4); + + let pointNames = stateVariables[graphName].activeChildren.map( + (x) => x.componentName, + ); + + for (let [ind, val] of pointsByGraph[graphInd].entries()) { + expect( + stateVariables[pointNames[ind]].stateValues.xs.map( + (x) => x.tree, + ), + ).eqls(val); + } + } + }); + + it("map with copies", async () => { + let core = await createTestCore({ + doenetML: ` + +

+ + +

+ x +

$map1

+ `, + }); + + let texts: string[] = []; + for (let [n, j] of [ + [3, 1], + [4, 2], + ]) { + let b = n; + let i = j; + let constant = n + j + b + i; + texts.push(`x + 2 z + ${constant} and x`); + } + + let pText = texts.join(", "); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p1"].stateValues.text).eq(pText); + expect(stateVariables["/p2"].stateValues.text).eq(pText); + }); + + it("map with copies, extended dynamically", async () => { + let core = await createTestCore({ + doenetML: ` + 1 +

+ + +

+ x +

$map1

+

+ + + + + `, + }); + + function textForLength(length: number) { + let sources = [...Array(length).keys()].map((v) => [v + 3, v + 1]); + + let texts: string[] = []; + for (let [n, j] of sources) { + let b = n; + let i = j; + let constant = n + j + b + i; + texts.push(`x + 2 z + ${constant} and x`); + } + + return texts.join(", "); + } + + let pText = textForLength(1); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq(pText); + expect(stateVariables["/p2"].stateValues.text).eq(pText); + expect(stateVariables["/p3"].stateValues.text).eq(pText); + + // Double the length then test again + await core.requestAction({ + componentName: "/uv", + actionName: "updateValue", + args: {}, + event: null, + }); + + pText = textForLength(2); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq(pText); + expect(stateVariables["/p2"].stateValues.text).eq(pText); + expect(stateVariables["/p3"].stateValues.text).eq(pText); + + // Double the length again then test one more time + await core.requestAction({ + componentName: "/uv", + actionName: "updateValue", + args: {}, + event: null, + }); + + pText = textForLength(4); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq(pText); + expect(stateVariables["/p2"].stateValues.text).eq(pText); + expect(stateVariables["/p3"].stateValues.text).eq(pText); + }); + + function sinTextFromVars(vars: string[]) { + let sources = vars.map((v, i) => [i + 1, v]); + + let texts: string[] = []; + for (let [i, x] of sources) { + if (i === 1) { + texts.push(`sin(${x})`); + } else { + texts.push(`sin(${i} ${x})`); + } + } + + return texts.join(", "); + } + + it("map with copied template", async () => { + let core = await createTestCore({ + doenetML: ` +

+ + xy +

+ +

+ $template1 + qp +

+ +

$map2

+ `, + }); + + let pText1 = sinTextFromVars(["x", "y"]); + let pText2 = sinTextFromVars(["q", "p"]); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p1"].stateValues.text).eq(pText1); + expect(stateVariables["/p2"].stateValues.text).eq(pText2); + expect(stateVariables["/p3"].stateValues.text).eq(pText2); + }); + + it("map with new namespace but no new namespace on template", async () => { + let core = await createTestCore({ + doenetML: ` +

+ + xy +

+ +

$map1

+ `, + }); + + let pText = sinTextFromVars(["x", "y"]); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq(pText); + expect(stateVariables["/p2"].stateValues.text).eq(pText); + }); + + it("graph with new namespace and assignNames", async () => { + let core = await createTestCore({ + doenetML: ` + $(/hi/c/P.coords{assignNames="c1"}) + $(/hi/s/P.coords{assignNames="c2"}) + $(/hi/q/P.coords{assignNames="c3"}) + + + + + + + + + `, + }); + + let points: number[][] = []; + for (let m = 1; m <= 2; m++) { + for (let n = -3; n <= -2; n++) { + points.push([m, n]); + } + } + + let stateVariables = await returnAllStateVariables(core); + let replacementNames = stateVariables["/hi/map1"].replacements!.map( + (x) => + stateVariables[x.componentName].replacements![0].componentName, + ); + + expect( + stateVariables["/hi"].stateValues.graphicalDescendants.length, + ).eq(4); + expect( + stateVariables["/hi/q/P"].stateValues.xs.map((x) => x.tree), + ).eqls(points[0]); + expect( + stateVariables["/hi/c/P"].stateValues.xs.map((x) => x.tree), + ).eqls(points[1]); + expect( + stateVariables["/hi/s/P"].stateValues.xs.map((x) => x.tree), + ).eqls(points[2]); + + expect( + stateVariables[replacementNames[3]].stateValues.xs.map( + (x) => x.tree, + ), + ).eqls(points[3]); + + expect(stateVariables["/c1"].stateValues.value.tree).eqls([ + "vector", + ...points[1], + ]); + expect(stateVariables["/c2"].stateValues.value.tree).eqls([ + "vector", + ...points[2], + ]); + expect(stateVariables["/c3"].stateValues.value.tree).eqls([ + "vector", + ...points[0], + ]); + }); + + it("map copying value from source of other map", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + `, + }); + + let e_n2 = 6; + + let maths1 = [1, 2, 3].map((n) => `( ${n}, ${e_n2} )`); + let maths2 = [4, 5, 6].map((n) => `sin(${n})`); + let names1 = ["/u/math", "/v/math", "/w/math"]; + let names2 = ["/c/math", "/d/math", "/e/math"]; + + let stateVariables = await returnAllStateVariables(core); + + for (let i = 0; i < 3; i++) { + expect(stateVariables[names1[i]].stateValues.text).eq(maths1[i]); + expect(stateVariables[names2[i]].stateValues.text).eq(maths2[i]); + } + }); + + it("map length depending on other map", async () => { + let core = await createTestCore({ + doenetML: ` +

+ + +

+ `, + }); + + let texts: string[] = []; + + for (let b of [1, 2, 3]) { + for (let a of [...Array(b).keys()].map((v) => v + 1)) { + texts.push(`( ${a}, ${b} )`); + } + } + + let pText = texts.join(", "); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p"].stateValues.text).eq(pText); + }); + + it("map begins zero length, copied multiple times", async () => { + let core = await createTestCore({ + doenetML: ` +

+ + + + +

+ + + + + +

$map1{name="copyMap2"}

+

$copyMap2{name="copyMap3"}

+ + $p1{name="p4"} + $p4{name="p5"} + $p5{name="p6"} + + `, + }); + + async function check_items(from: number, to: number, count: number) { + let step = (to - from) / (count - 1); + + let maths: number[] = []; + for (let i = 0; i < count; i++) { + let n = from + (i ? i * step : 0); + maths.push(n ** 2); + } + + let pText = maths.join(", "); + + const stateVariables = await returnAllStateVariables(core); + for (let i = 1; i <= 6; i++) { + expect(stateVariables[`/p${i}`].stateValues.text).eq(pText); + } + } + + // At beginning, nothing shown + let from = 1, + to = 2, + count = 0; + await check_items(from, to, count); + + // make sequence length 1 + count = 1; + await updateMathInputValue({ + latex: count.toString(), + componentName: "/sequenceCount", + core, + }); + await check_items(from, to, count); + + // make sequence length 0 again + count = 0; + await updateMathInputValue({ + latex: count.toString(), + componentName: "/sequenceCount", + core, + }); + await check_items(from, to, count); + + // make sequence length 2 + count = 2; + await updateMathInputValue({ + latex: count.toString(), + componentName: "/sequenceCount", + core, + }); + await check_items(from, to, count); + + // change limits + from = 3; + to = 5; + await updateMathInputValue({ + latex: from.toString(), + componentName: "/sequenceFrom", + core, + }); + await updateMathInputValue({ + latex: to.toString(), + componentName: "/sequenceTo", + core, + }); + await check_items(from, to, count); + + // make sequence length 0 again + count = 0; + await updateMathInputValue({ + latex: count.toString(), + componentName: "/sequenceCount", + core, + }); + await check_items(from, to, count); + + // make sequence length 3 + count = 3; + await updateMathInputValue({ + latex: count.toString(), + componentName: "/sequenceCount", + core, + }); + await check_items(from, to, count); + }); + + it("map with seemingly circular dependence in template", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + 1 + 1 + + + + + + + `, + }); + + function points_from_pars(q: number, r: number) { + let P1s: number[][] = []; + let P2s: number[][] = []; + + for (let n = 2; n <= 4; n++) { + let P1x = q * n ** 2; + let P2x = r * n; + + P1s.push(rnd([P1x, P2x])); + P2s.push(rnd([P2x, P1x])); + } + + return { P1s, P2s }; + } + + /** + * Round numerical components of `vec` to 12 digits. + * + * Used to eliminate differences due to round off error + */ + function rnd(vec: any[]) { + return vec.map((v) => + Number.isFinite(v) ? Math.round(v * 1e12) / 1e12 : v, + ); + } + + async function check_items(q: number, r: number) { + let { P1s, P2s } = points_from_pars(q, r); + + let nameSpaces = ["/a", "/b", "/c"]; + + const stateVariables = await returnAllStateVariables(core); + + for (let [ind, ns] of nameSpaces.entries()) { + expect( + rnd( + stateVariables[`${ns}/P1`].stateValues.xs.map( + (x) => x.tree, + ), + ), + ).eqls(P1s[ind]); + expect( + rnd( + stateVariables[`${ns}/P2`].stateValues.xs.map( + (x) => x.tree, + ), + ), + ).eqls(P2s[ind]); + + expect( + rnd( + stateVariables[`/c${ind * 2 + 1}`].stateValues.value + .tree, + ), + ).eqls(["vector", ...P1s[ind]]); + expect( + rnd( + stateVariables[`/c${ind * 2 + 2}`].stateValues.value + .tree, + ), + ).eqls(["vector", ...P2s[ind]]); + } + } + + let q = 1, + r = 1; + + await check_items(q, r); + + // move point /a/P1 + r = 1.3; + q = -2.1; + + let P1s = points_from_pars(q, r).P1s; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/a/P1", + args: { x: P1s[0][0], y: P1s[0][1] }, + event: null, + }); + await check_items(q, r); + + // move point /a/P2 + r = 0.7; + q = 1.8; + let P2s = points_from_pars(q, r).P2s; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/a/P2", + args: { x: P2s[0][0], y: P2s[0][1] }, + event: null, + }); + await check_items(q, r); + + // move point /b/P1 + r = -0.2; + q = 0.3; + P1s = points_from_pars(q, r).P1s; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/b/P1", + args: { x: P1s[1][0], y: P1s[1][1] }, + event: null, + }); + await check_items(q, r); + + // move point /b/P2 + r = 0.6; + q = 0.35; + P2s = points_from_pars(q, r).P2s; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/b/P2", + args: { x: P2s[1][0], y: P2s[1][1] }, + event: null, + }); + await check_items(q, r); + + // move point /c/P1 + r = -0.21; + q = -0.46; + P1s = points_from_pars(q, r).P1s; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/c/P1", + args: { x: P1s[2][0], y: P1s[2][1] }, + event: null, + }); + await check_items(q, r); + + // move point /c/P2 + r = 0.37; + q = -0.73; + P2s = points_from_pars(q, r).P2s; + + await core.requestAction({ + actionName: "movePoint", + componentName: "/c/P2", + args: { x: P2s[2][0], y: P2s[2][1] }, + event: null, + }); + await check_items(q, r); + }); + + it("two maps with mutual copies, begin zero length, copied multiple times", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + `, + }); + + async function check_items(from: number, to: number, count: number) { + let a_Px = -from; + let q_Px = from; + + let step = (to - from) / (count - 1); + + let points1: number[][] = []; + let points2: number[][] = []; + for (let i = 0; i < count; i++) { + let n = from + (i ? i * step : 0); + points1.push([-n, n * q_Px]); + points2.push([n, n * a_Px]); + } + + let ns1 = ["/a", "/b", "/c"]; + let ns2 = ["/q", "/r", "/s"]; + let ns1Prefixes = ["", "/copyMap1", "/copyMap1b", "/g4"]; + let ns2Prefixes = ["", "/copyMap2", "/copyMap2b", "/g4"]; + + const stateVariables = await returnAllStateVariables(core); + + expect( + stateVariables["/g1"].stateValues.graphicalDescendants.length, + ).eq(2 * count); + expect( + stateVariables["/g2"].stateValues.graphicalDescendants.length, + ).eq(2 * count); + expect( + stateVariables["/g3"].stateValues.graphicalDescendants.length, + ).eq(2 * count); + expect( + stateVariables["/g4"].stateValues.graphicalDescendants.length, + ).eq(2 * count); + + for (let i = 0; i < count; i++) { + for (let pre of ns1Prefixes) { + expect( + stateVariables[`${pre}${ns1[i]}/P`].stateValues.xs.map( + (x) => x.tree, + ), + ).eqls(points1[i]); + } + for (let pre of ns2Prefixes) { + expect( + stateVariables[`${pre}${ns2[i]}/P`].stateValues.xs.map( + (x) => x.tree, + ), + ).eqls(points2[i]); + } + } + } + + // At beginning, nothing shown + let from = 1, + to = 2, + count = 0; + await check_items(from, to, count); + + // make sequence length 1 + count = 1; + await updateMathInputValue({ + latex: count.toString(), + componentName: "/sequenceCount", + core, + }); + await check_items(from, to, count); + + // make sequence length 0 again + count = 0; + await updateMathInputValue({ + latex: count.toString(), + componentName: "/sequenceCount", + core, + }); + await check_items(from, to, count); + + // make sequence length 2 + count = 2; + await updateMathInputValue({ + latex: count.toString(), + componentName: "/sequenceCount", + core, + }); + await check_items(from, to, count); + + // change limits + from = 3; + to = 5; + await updateMathInputValue({ + latex: from.toString(), + componentName: "/sequenceFrom", + core, + }); + await updateMathInputValue({ + latex: to.toString(), + componentName: "/sequenceTo", + core, + }); + await check_items(from, to, count); + + // make sequence length 0 again + count = 0; + await updateMathInputValue({ + latex: count.toString(), + componentName: "/sequenceCount", + core, + }); + await check_items(from, to, count); + + // make sequence length 3 + count = 3; + await updateMathInputValue({ + latex: count.toString(), + componentName: "/sequenceCount", + core, + }); + await check_items(from, to, count); + }); + + it("map points to adapt to math", async () => { + // Note: math1 ends up getting math children from the map. + // We aren't worrying about the interpretation of + // the juxtaposition of vectors that the children represent. + // We're just checking that the points from the map + // are adapted into maths due to their math parent. + let core = await createTestCore({ + doenetML: ` +

Number of points:

+

Step size:

+ + + + + + + + + + `, + }); + + async function check_math_children(numPoints: number, step: number) { + let from = 2; + + if (step === 0) { + numPoints = 0; + } + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/math1"].activeChildren.length).eq( + numPoints, + ); + + for (let i = 0; i < numPoints; i++) { + let n = from + i * step; + let child = + stateVariables[ + stateVariables["/math1"].activeChildren[i].componentName + ]; + // Note: coords is a type of math + expect(child.componentType).eq("coords"); + + if (Number.isInteger(n)) { + expect(child.stateValues.value.tree).eqls([ + "vector", + n, + ["apply", "sin", n], + ]); + } else { + let val = child.stateValues.value.tree; + expect(val[0]).eq("vector"); + expect(val[1]).eq(n); + expect(val[2]).closeTo(Math.sin(n), 1e14); + } + } + } + + // use 0 as a stand-in for undefined + let numPoints = 0; + let step = 0; + + await check_math_children(numPoints, step); + + numPoints = 10; + await updateMathInputValue({ + latex: numPoints.toString(), + componentName: "/number", + core, + }); + await check_math_children(numPoints, step); + + step = 1; + await updateMathInputValue({ + latex: step.toString(), + componentName: "/step", + core, + }); + await check_math_children(numPoints, step); + + numPoints = 20; + await updateMathInputValue({ + latex: numPoints.toString(), + componentName: "/number", + core, + }); + await check_math_children(numPoints, step); + + step = 0.5; + await updateMathInputValue({ + latex: step.toString(), + componentName: "/step", + core, + }); + await check_math_children(numPoints, step); + + numPoints = 10; + await updateMathInputValue({ + latex: numPoints.toString(), + componentName: "/number", + core, + }); + await check_math_children(numPoints, step); + + // use 0 as a stand-in for undefined + step = 0; + await updateMathInputValue({ + latex: "", + componentName: "/step", + core, + }); + await check_math_children(numPoints, step); + + numPoints = 5; + await updateMathInputValue({ + latex: numPoints.toString(), + componentName: "/number", + core, + }); + await check_math_children(numPoints, step); + + step = -3; + await updateMathInputValue({ + latex: step.toString(), + componentName: "/step", + core, + }); + await check_math_children(numPoints, step); + }); + + it("map inside sources of map", async () => { + let core = await createTestCore({ + doenetML: ` +

Number of points:

+ + + + + + + + + + + + $m1 + + + +

$p1

+

$(p1/pt)

+

$p2

+

$(p2/pt)

+

$p3

+

$(p3/pt)

+ +

$q1

+

$(q1/pt)

+

$q2

+

$(q2/pt)

+

$q3

+

$(q3/pt)

+ + `, + }); + + async function check_items(num: number) { + let sources1 = [...Array(num).keys()].map((x) => x + 1); + + let points1 = sources1.map((n) => [n, 2 * n]); + let points2 = points1.map((p) => [p[0] ** 2, p[1] ** 2]); + + let point1Texts = points1.map((p) => `( ${p[0]}, ${p[1]} )`); + let point2Texts = points2.map((p) => `( ${p[0]}, ${p[1]} )`); + + let pNames1 = [ + ["/p1a", "/p1b"], + ["/p2a", "/p2b"], + ["/p3a", "/p3b"], + ]; + let pNames2 = [ + ["/q1a", "/q1b"], + ["/q2a", "/q2b"], + ["/q3a", "/q3b"], + ]; + + const stateVariables = await returnAllStateVariables(core); + for (let n = 0; n < 3; n++) { + for (let i = 0; i < 2; i++) { + expect(stateVariables[pNames1[n][i]].stateValues.text).eq( + point1Texts[n] || "", + ); + expect(stateVariables[pNames2[n][i]].stateValues.text).eq( + point2Texts[n] || "", + ); + } + } + } + + let num = 0; + + await check_items(num); + + // set number to be 2 + num = 2; + await updateMathInputValue({ + latex: num.toString(), + componentName: "/number", + core, + }); + await check_items(num); + + // set number to be 1 + num = 1; + await updateMathInputValue({ + latex: num.toString(), + componentName: "/number", + core, + }); + await check_items(num); + + // set number to be 3 + num = 3; + await updateMathInputValue({ + latex: num.toString(), + componentName: "/number", + core, + }); + await check_items(num); + + // set number back to zero + num = 0; + await updateMathInputValue({ + latex: num.toString(), + componentName: "/number", + core, + }); + await check_items(num); + + // set number back to 1 + num = 1; + await updateMathInputValue({ + latex: num.toString(), + componentName: "/number", + core, + }); + await check_items(num); + }); + + it("can override fixed of source index", async () => { + let core = await createTestCore({ + doenetML: ` + + + redyellow + + + + redyellow + + + + `, + }); + + async function check_items(a: number, b: number, c: number, d: number) { + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a/ind"].stateValues.value).eqls(a); + expect(stateVariables["/b/ind"].stateValues.value).eqls(b); + expect(stateVariables["/c/ind"].stateValues.value).eqls(c); + expect(stateVariables["/d/ind"].stateValues.value).eqls(d); + } + + async function set_items(a: string, b: string, c: string, d: string) { + await updateMathInputValue({ + latex: a, + componentName: "/a/mi", + core, + }); + await updateMathInputValue({ + latex: b, + componentName: "/b/mi", + core, + }); + await updateMathInputValue({ + latex: c, + componentName: "/c/mi", + core, + }); + await updateMathInputValue({ + latex: d, + componentName: "/d/mi", + core, + }); + } + + await check_items(1, 2, 1, 2); + + await set_items("3", "4", "5", "6"); + await check_items(1, 2, 5, 6); + + await set_items("x", "x", "x", "x"); + await check_items(1, 2, NaN, NaN); + + await set_items("7", "8", "9", "10"); + await check_items(1, 2, 9, 10); + }); + + it("maps hide dynamically", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + +

Length of map 1:

+

Length of map 2:

+ +

map 1: + + +

+

map 2: + + +

+ `, + }); + + async function check_items( + h1: boolean, + h2: boolean, + n1: number, + n2: number, + ) { + const stateVariables = await returnAllStateVariables(core); + + if (h1) { + expect(stateVariables["/m1"].stateValues.text).eq("map 1: "); + } else { + let m1text = + "map 1: " + + [...Array(n1).keys()].map((v) => `hi${v + 1}`).join(", "); + expect(stateVariables["/m1"].stateValues.text).eq(m1text); + } + + if (h2) { + expect(stateVariables["/m2"].stateValues.text).eq("map 2: "); + } else { + let m2text = + "map 2: " + + [...Array(n2).keys()].map((v) => `hi${v + 1}`).join(", "); + expect(stateVariables["/m2"].stateValues.text).eq(m2text); + } + } + + async function set_ns(n1: number, n2: number) { + await updateMathInputValue({ + latex: n1.toString(), + componentName: "/n1", + core, + }); + await updateMathInputValue({ + latex: n2.toString(), + componentName: "/n2", + core, + }); + } + + async function set_hs(h1: boolean, h2: boolean) { + await updateBooleanInputValue({ + boolean: h1, + componentName: "/h1", + core, + }); + await updateBooleanInputValue({ + boolean: h2, + componentName: "/h2", + core, + }); + } + + let h1 = false, + h2 = true, + n1 = 4, + n2 = 4; + + await check_items(h1, h2, n1, n2); + + n1 = 6; + n2 = 6; + await set_ns(n1, n2); + await check_items(h1, h2, n1, n2); + + h1 = true; + h2 = false; + await set_hs(h1, h2); + await check_items(h1, h2, n1, n2); + + n1 = 8; + n2 = 8; + await set_ns(n1, n2); + await check_items(h1, h2, n1, n2); + + h1 = false; + h2 = true; + await set_hs(h1, h2); + await check_items(h1, h2, n1, n2); + + n1 = 3; + n2 = 3; + await set_ns(n1, n2); + await check_items(h1, h2, n1, n2); + + h1 = true; + h2 = false; + await set_hs(h1, h2); + await check_items(h1, h2, n1, n2); + + n1 = 4; + n2 = 4; + await set_ns(n1, n2); + await check_items(h1, h2, n1, n2); + }); + + function create_as_list_template(inner_content: string) { + return ` +

+ + + + +

+

+ + + + +

+

+ + + + +

+

$default

+

$nocommas

+

$withcommas

+

$default{asList="false"}

+

$withcommas{asList="false"}

+

$nocommas{asList="true"}

+

+

+

+

+

+

+

+

+

+ `; + } + + async function test_as_list_maps(core, items: string[]) { + let pTextCommas = items.join(", "); + let pTextNoCommas = items.join(" "); + + let commaNames = [ + "/pdefault", + "/pwithcommas", + "/pdefault2", + "/pwithcommas2", + "/pwithcommas3", + "/pdefault4", + "/pwithcommas4", + "/pdefault5", + "/pwithcommas5", + "/pwithcommas6", + ]; + let noCommaNames = [ + "/pnocommas", + "/pnocommas2", + "/pnocommas3", + "/pnocommas3a", + "/pnocommas4", + "/pnocommas5", + "/pnocommas6", + "/pnocommas6a", + ]; + + const stateVariables = await returnAllStateVariables(core); + + for (let name of commaNames) { + // Note: we do not remove whitespace that has a following commas, + // as we want to test that the whitespace before a comma is removed. + + expect( + stateVariables[name].stateValues.text + .replace(/\s+(?!,)/g, " ") + .trim(), + ).eq(pTextCommas); + } + for (let name of noCommaNames) { + expect( + stateVariables[name].stateValues.text + .replace(/\s+(?!,)/g, " ") + .trim(), + ).eq(pTextNoCommas); + } + } + + it("map displays as list by default, single number in template", async () => { + let core = await createTestCore({ + doenetML: create_as_list_template(`$v^2`), + }); + + let numbers = [...Array(10).keys()].map((v) => String((v + 1) ** 2)); + + await test_as_list_maps(core, numbers); + }); + + it("map displays as list by default, number and string in template", async () => { + let core = await createTestCore({ + doenetML: create_as_list_template(` + $v^2 + x`), + }); + + let numbers = [...Array(10).keys()].map( + (v) => String((v + 1) ** 2) + " x", + ); + + await test_as_list_maps(core, numbers); + }); + + it("map displays as list by default, number, string and math in template", async () => { + let core = await createTestCore({ + doenetML: create_as_list_template(` + $v^2 + x`), + }); + + let numbers = [...Array(10).keys()].map( + (v) => String((v + 1) ** 2) + " x", + ); + + await test_as_list_maps(core, numbers); + }); + + it("map will display as list even if if has non-inline components with canBeInList set", async () => { + let core = await createTestCore({ + doenetML: ` +

+ + +

+

+ + +

+

+ + +

+

+ + +

+ `, + }); + + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq( + "( 1, 1 ), ( 2, 4 ), ( 3, 9 )", + ); + expect(stateVariables["/p2"].stateValues.text).eq( + "( 1, 1 ), ( 2, 4 ), ( 3, 9 )", + ); + expect(stateVariables["/p3"].stateValues.text).eq( + "y = 1, y = 2, y = 3", + ); + expect(stateVariables["/p4"].stateValues.text).eq("2, 4, 6"); + }); + + it("properly create unique name to avoid duplicate names", async () => { + // Key point: second number in template is not assigned a name + // and there is no new namespace. Make sure the names created + // for the two instances of the second number do not collide. + let core = await createTestCore({ + doenetML: ` + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + // Note: filter out strings by only including replacements + // with a component type + let n1a = stateVariables[ + stateVariables["/map1"].replacements![0].componentName + ].replacements!.filter((s) => s.componentType)[1].componentName; + let n2a = stateVariables[ + stateVariables["/map1"].replacements![1].componentName + ].replacements!.filter((s) => s.componentType)[1].componentName; + + expect(stateVariables["/n1"].stateValues.value).eq(1); + expect(stateVariables[n1a].stateValues.value).eq(10); + expect(stateVariables["/n2"].stateValues.value).eq(2); + expect(stateVariables[n2a].stateValues.value).eq(20); + }); + + it("bug for isResponse and parallel is fixed", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + `, + }); + + const stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/p1"].stateValues.text).eq("hi 1"); + expect(stateVariables["/p2"].stateValues.text).eq("hi 2"); + expect(stateVariables["/p1"].stateValues.isResponse).eq(true); + expect(stateVariables["/p2"].stateValues.isResponse).eq(true); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/math.test.ts b/packages/doenetml-worker/src/test/tagSpecific/math.test.ts index 55e581617..c1d01426a 100644 --- a/packages/doenetml-worker/src/test/tagSpecific/math.test.ts +++ b/packages/doenetml-worker/src/test/tagSpecific/math.test.ts @@ -7857,7 +7857,6 @@ describe("Math tag tests", async () => {

FixLocation 2: $fixLocation2

Change fixLocation 1

Change fixLocation 2

-

`, }); diff --git a/packages/doenetml-worker/src/test/tagSpecific/mathinput.test.ts b/packages/doenetml-worker/src/test/tagSpecific/mathinput.test.ts index 6c8179b2a..b96a28338 100644 --- a/packages/doenetml-worker/src/test/tagSpecific/mathinput.test.ts +++ b/packages/doenetml-worker/src/test/tagSpecific/mathinput.test.ts @@ -345,7 +345,7 @@ describe("MathInput tag tests", async () => { ]); expect(stateVariables["/mi2"].stateValues.value.tree).to.eq("\uFF3F"); - // update value (e.g., press enter) in mathInput 3 + // update value (e.g., update value) in mathInput 3 await updateMathInputValueToImmediateValue({ componentName: "/mi2", core, @@ -1066,7 +1066,7 @@ describe("MathInput tag tests", async () => { expect(stateVariables["/mi1"].stateValues.value.tree).eqls("_"); expect(stateVariables["/mi1a"].stateValues.value.tree).eqls("_"); - // Update value (e.g., press enter) + // Update value (e.g., update value) await updateMathInputValueToImmediateValue({ componentName: "/mi1", core, @@ -1299,7 +1299,7 @@ describe("MathInput tag tests", async () => { ["-", ["*", "y", "_"]], ]); - // Update value (e.g., press enter) + // Update value (e.g., update value) await updateMathInputValueToImmediateValue({ componentName: "/mi1", core, @@ -1427,7 +1427,7 @@ describe("MathInput tag tests", async () => { "y", ]); - // press enter + // update value await updateMathInputValueToImmediateValue({ componentName: "/mi1", core, @@ -1785,7 +1785,7 @@ describe("MathInput tag tests", async () => { "y", ]); - // press enter + // update value await updateMathInputValueToImmediateValue({ componentName: "/mi1", core, @@ -2230,7 +2230,7 @@ describe("MathInput tag tests", async () => { ["*", 2, "x", "z"], ]); - // value revert when updateValue (e.g., press enter) + // value revert when updateValue (e.g., update value) await updateMathInputValueToImmediateValue({ componentName: "/mi1", core, @@ -8644,238 +8644,229 @@ describe("MathInput tag tests", async () => { `; + async function check_items( + [mi1, mi2, mi3, mi4]: [ + mi1: string, + mi2: string, + mi3: string, + mi4: string, + ], + [mi1iv, mi2iv, mi3iv, mi4iv]: [ + mi1iv: string, + mi2iv: string, + mi3iv: string, + mi4iv: string, + ], + [mi1changed, mi2changed, mi3changed, mi4changed]: [ + mi1changed: boolean, + mi2changed: boolean, + mi3changed: boolean, + mi4changed: boolean, + ], + [mi1ivchanged, mi2ivchanged, mi3ivchanged, mi4ivchanged]: [ + mi1ivchanged: boolean, + mi2ivchanged: boolean, + mi3ivchanged: boolean, + mi4ivchanged: boolean, + ], + ) { + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/mi1"].stateValues.value.tree).eq(mi1); + expect(stateVariables["/mi2"].stateValues.value.tree).eq(mi2); + expect(stateVariables["/mi3"].stateValues.value.tree).eq(mi3); + expect(stateVariables["/mi4"].stateValues.value.tree).eq(mi4); + + expect(stateVariables["/mi1a"].stateValues.value.tree).eq(mi1); + expect(stateVariables["/mi2a"].stateValues.value.tree).eq(mi2); + expect(stateVariables["/mi3a"].stateValues.value.tree).eq(mi3); + expect(stateVariables["/mi4a"].stateValues.value.tree).eq(mi4); + + expect(stateVariables["/mi1iva"].stateValues.value.tree).eq(mi1iv); + expect(stateVariables["/mi2iva"].stateValues.value.tree).eq(mi2iv); + expect(stateVariables["/mi3iva"].stateValues.value.tree).eq(mi3iv); + expect(stateVariables["/mi4iva"].stateValues.value.tree).eq(mi4iv); + + expect(stateVariables["/mi1changed"].stateValues.value).eq( + mi1changed, + ); + expect(stateVariables["/mi2changed"].stateValues.value).eq( + mi2changed, + ); + expect(stateVariables["/mi3changed"].stateValues.value).eq( + mi3changed, + ); + expect(stateVariables["/mi4changed"].stateValues.value).eq( + mi4changed, + ); + + expect(stateVariables["/mi1ivchanged"].stateValues.value).eq( + mi1ivchanged, + ); + expect(stateVariables["/mi2ivchanged"].stateValues.value).eq( + mi2ivchanged, + ); + expect(stateVariables["/mi3ivchanged"].stateValues.value).eq( + mi3ivchanged, + ); + expect(stateVariables["/mi4ivchanged"].stateValues.value).eq( + mi4ivchanged, + ); + } + let core = await createTestCore({ doenetML, }); + let mi1 = "\uff3f", + mi2 = "x", + mi3 = "\uff3f", + mi4 = "x"; + let mi1iv = "\uff3f", + mi2iv = "x", + mi3iv = "\uff3f", + mi4iv = "x"; + let mi1changed = false, + mi2changed = false, + mi3changed = false, + mi4changed = false; + let mi1ivchanged = false, + mi2ivchanged = false, + mi3ivchanged = false, + mi4ivchanged = false; + + await check_items( + [mi1, mi2, mi3, mi4], + [mi1iv, mi2iv, mi3iv, mi4iv], + [mi1changed, mi2changed, mi3changed, mi4changed], + [mi1ivchanged, mi2ivchanged, mi3ivchanged, mi4ivchanged], + ); + let stateVariables = await returnAllStateVariables(core); - expect(stateVariables["/mi1a"].stateValues.value.tree).eqls("\uff3f"); - expect(stateVariables["/mi2a"].stateValues.value.tree).eqls("x"); - expect(stateVariables["/mi3a"].stateValues.value.tree).eqls("\uff3f"); - expect(stateVariables["/mi4a"].stateValues.value.tree).eqls("x"); - expect(stateVariables["/mi1iva"].stateValues.value.tree).eqls("\uff3f"); - expect(stateVariables["/mi2iva"].stateValues.value.tree).eqls("x"); - expect(stateVariables["/mi3iva"].stateValues.value.tree).eqls("\uff3f"); - expect(stateVariables["/mi4iva"].stateValues.value.tree).eqls("x"); - - expect(stateVariables["/mi1changed"].stateValues.value).eq(false); - expect(stateVariables["/mi2changed"].stateValues.value).eq(false); - expect(stateVariables["/mi3changed"].stateValues.value).eq(false); - expect(stateVariables["/mi4changed"].stateValues.value).eq(false); - expect(stateVariables["/mi1ivchanged"].stateValues.value).eq(false); - expect(stateVariables["/mi2ivchanged"].stateValues.value).eq(false); - expect(stateVariables["/mi3ivchanged"].stateValues.value).eq(false); - expect(stateVariables["/mi4ivchanged"].stateValues.value).eq(false); // type in first marks only first immediate value as changed - + mi1iv = "y"; + mi1ivchanged = true; await updateMathInputImmediateValue({ - latex: "y", + latex: mi1iv, componentName: "/mi1", core, }); - stateVariables = await returnAllStateVariables(core); - - expect(stateVariables["/mi1a"].stateValues.value.tree).eqls("\uff3f"); - expect(stateVariables["/mi2a"].stateValues.value.tree).eqls("x"); - expect(stateVariables["/mi3a"].stateValues.value.tree).eqls("\uff3f"); - expect(stateVariables["/mi4a"].stateValues.value.tree).eqls("x"); - expect(stateVariables["/mi1iva"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi2iva"].stateValues.value.tree).eqls("x"); - expect(stateVariables["/mi3iva"].stateValues.value.tree).eqls("\uff3f"); - expect(stateVariables["/mi4iva"].stateValues.value.tree).eqls("x"); - - expect(stateVariables["/mi1changed"].stateValues.value).eq(false); - expect(stateVariables["/mi2changed"].stateValues.value).eq(false); - expect(stateVariables["/mi3changed"].stateValues.value).eq(false); - expect(stateVariables["/mi4changed"].stateValues.value).eq(false); - expect(stateVariables["/mi1ivchanged"].stateValues.value).eq(true); - expect(stateVariables["/mi2ivchanged"].stateValues.value).eq(false); - expect(stateVariables["/mi3ivchanged"].stateValues.value).eq(false); - expect(stateVariables["/mi4ivchanged"].stateValues.value).eq(false); - // press enter in first marks only first value as changed + await check_items( + [mi1, mi2, mi3, mi4], + [mi1iv, mi2iv, mi3iv, mi4iv], + [mi1changed, mi2changed, mi3changed, mi4changed], + [mi1ivchanged, mi2ivchanged, mi3ivchanged, mi4ivchanged], + ); + // update value in first marks only first value as changed + mi1 = mi3 = mi3iv = mi1iv; + mi1changed = true; await updateMathInputValueToImmediateValue({ componentName: "/mi1", core, }); - stateVariables = await returnAllStateVariables(core); - expect(stateVariables["/mi1a"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi2a"].stateValues.value.tree).eqls("x"); - expect(stateVariables["/mi3a"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi4a"].stateValues.value.tree).eqls("x"); - expect(stateVariables["/mi1iva"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi2iva"].stateValues.value.tree).eqls("x"); - expect(stateVariables["/mi3iva"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi4iva"].stateValues.value.tree).eqls("x"); - - expect(stateVariables["/mi1changed"].stateValues.value).eq(true); - expect(stateVariables["/mi2changed"].stateValues.value).eq(false); - expect(stateVariables["/mi3changed"].stateValues.value).eq(false); - expect(stateVariables["/mi4changed"].stateValues.value).eq(false); - expect(stateVariables["/mi1ivchanged"].stateValues.value).eq(true); - expect(stateVariables["/mi2ivchanged"].stateValues.value).eq(false); - expect(stateVariables["/mi3ivchanged"].stateValues.value).eq(false); - expect(stateVariables["/mi4ivchanged"].stateValues.value).eq(false); + await check_items( + [mi1, mi2, mi3, mi4], + [mi1iv, mi2iv, mi3iv, mi4iv], + [mi1changed, mi2changed, mi3changed, mi4changed], + [mi1ivchanged, mi2ivchanged, mi3ivchanged, mi4ivchanged], + ); // type in second marks only second immediate value as changed + mi4 = mi4iv = mi2iv = "z"; + mi2ivchanged = true; await updateMathInputImmediateValue({ - latex: "z", + latex: mi2iv, componentName: "/mi2", core, }); - stateVariables = await returnAllStateVariables(core); - - expect(stateVariables["/mi1a"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi2a"].stateValues.value.tree).eqls("x"); - expect(stateVariables["/mi3a"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi4a"].stateValues.value.tree).eqls("z"); - expect(stateVariables["/mi1iva"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi2iva"].stateValues.value.tree).eqls("z"); - expect(stateVariables["/mi3iva"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi4iva"].stateValues.value.tree).eqls("z"); - expect(stateVariables["/mi1changed"].stateValues.value).eq(true); - expect(stateVariables["/mi2changed"].stateValues.value).eq(false); - expect(stateVariables["/mi3changed"].stateValues.value).eq(false); - expect(stateVariables["/mi4changed"].stateValues.value).eq(false); - expect(stateVariables["/mi1ivchanged"].stateValues.value).eq(true); - expect(stateVariables["/mi2ivchanged"].stateValues.value).eq(true); - expect(stateVariables["/mi3ivchanged"].stateValues.value).eq(false); - expect(stateVariables["/mi4ivchanged"].stateValues.value).eq(false); + await check_items( + [mi1, mi2, mi3, mi4], + [mi1iv, mi2iv, mi3iv, mi4iv], + [mi1changed, mi2changed, mi3changed, mi4changed], + [mi1ivchanged, mi2ivchanged, mi3ivchanged, mi4ivchanged], + ); - // press enter in second marks only second value as changed + // update value in second marks only second value as changed + mi2 = mi2iv; + mi2changed = true; await updateMathInputValueToImmediateValue({ componentName: "/mi2", core, }); - stateVariables = await returnAllStateVariables(core); - expect(stateVariables["/mi1a"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi2a"].stateValues.value.tree).eqls("z"); - expect(stateVariables["/mi3a"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi4a"].stateValues.value.tree).eqls("z"); - expect(stateVariables["/mi1iva"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi2iva"].stateValues.value.tree).eqls("z"); - expect(stateVariables["/mi3iva"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi4iva"].stateValues.value.tree).eqls("z"); - - expect(stateVariables["/mi1changed"].stateValues.value).eq(true); - expect(stateVariables["/mi2changed"].stateValues.value).eq(true); - expect(stateVariables["/mi3changed"].stateValues.value).eq(false); - expect(stateVariables["/mi4changed"].stateValues.value).eq(false); - expect(stateVariables["/mi1ivchanged"].stateValues.value).eq(true); - expect(stateVariables["/mi2ivchanged"].stateValues.value).eq(true); - expect(stateVariables["/mi3ivchanged"].stateValues.value).eq(false); - expect(stateVariables["/mi4ivchanged"].stateValues.value).eq(false); + await check_items( + [mi1, mi2, mi3, mi4], + [mi1iv, mi2iv, mi3iv, mi4iv], + [mi1changed, mi2changed, mi3changed, mi4changed], + [mi1ivchanged, mi2ivchanged, mi3ivchanged, mi4ivchanged], + ); // type in third marks third immediate value as changed - + mi3iv = "a"; + mi3ivchanged = true; await updateMathInputImmediateValue({ - latex: "a", + latex: mi3iv, componentName: "/mi3", core, }); - stateVariables = await returnAllStateVariables(core); - expect(stateVariables["/mi1a"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi2a"].stateValues.value.tree).eqls("z"); - expect(stateVariables["/mi3a"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi4a"].stateValues.value.tree).eqls("z"); - expect(stateVariables["/mi1iva"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi2iva"].stateValues.value.tree).eqls("z"); - expect(stateVariables["/mi3iva"].stateValues.value.tree).eqls("a"); - expect(stateVariables["/mi4iva"].stateValues.value.tree).eqls("z"); - - expect(stateVariables["/mi1changed"].stateValues.value).eq(true); - expect(stateVariables["/mi2changed"].stateValues.value).eq(true); - expect(stateVariables["/mi3changed"].stateValues.value).eq(false); - expect(stateVariables["/mi4changed"].stateValues.value).eq(false); - expect(stateVariables["/mi1ivchanged"].stateValues.value).eq(true); - expect(stateVariables["/mi2ivchanged"].stateValues.value).eq(true); - expect(stateVariables["/mi3ivchanged"].stateValues.value).eq(true); - expect(stateVariables["/mi4ivchanged"].stateValues.value).eq(false); + await check_items( + [mi1, mi2, mi3, mi4], + [mi1iv, mi2iv, mi3iv, mi4iv], + [mi1changed, mi2changed, mi3changed, mi4changed], + [mi1ivchanged, mi2ivchanged, mi3ivchanged, mi4ivchanged], + ); - // press enter in third marks third value as changed + // update value in third marks third value as changed + mi1 = mi1iv = mi3 = mi3iv; + mi3changed = true; await updateMathInputValueToImmediateValue({ componentName: "/mi3", core, }); - stateVariables = await returnAllStateVariables(core); - - expect(stateVariables["/mi1a"].stateValues.value.tree).eqls("a"); - expect(stateVariables["/mi2a"].stateValues.value.tree).eqls("z"); - expect(stateVariables["/mi3a"].stateValues.value.tree).eqls("a"); - expect(stateVariables["/mi4a"].stateValues.value.tree).eqls("z"); - expect(stateVariables["/mi1iva"].stateValues.value.tree).eqls("a"); - expect(stateVariables["/mi2iva"].stateValues.value.tree).eqls("z"); - expect(stateVariables["/mi3iva"].stateValues.value.tree).eqls("a"); - expect(stateVariables["/mi4iva"].stateValues.value.tree).eqls("z"); - expect(stateVariables["/mi1changed"].stateValues.value).eq(true); - expect(stateVariables["/mi2changed"].stateValues.value).eq(true); - expect(stateVariables["/mi3changed"].stateValues.value).eq(true); - expect(stateVariables["/mi4changed"].stateValues.value).eq(false); - expect(stateVariables["/mi1ivchanged"].stateValues.value).eq(true); - expect(stateVariables["/mi2ivchanged"].stateValues.value).eq(true); - expect(stateVariables["/mi3ivchanged"].stateValues.value).eq(true); - expect(stateVariables["/mi4ivchanged"].stateValues.value).eq(false); + await check_items( + [mi1, mi2, mi3, mi4], + [mi1iv, mi2iv, mi3iv, mi4iv], + [mi1changed, mi2changed, mi3changed, mi4changed], + [mi1ivchanged, mi2ivchanged, mi3ivchanged, mi4ivchanged], + ); // type in fourth marks fourth immediate value as changed - + mi4iv = "b"; + mi4ivchanged = true; await updateMathInputImmediateValue({ - latex: "b", + latex: mi4iv, componentName: "/mi4", core, }); - stateVariables = await returnAllStateVariables(core); - expect(stateVariables["/mi1a"].stateValues.value.tree).eqls("a"); - expect(stateVariables["/mi2a"].stateValues.value.tree).eqls("z"); - expect(stateVariables["/mi3a"].stateValues.value.tree).eqls("a"); - expect(stateVariables["/mi4a"].stateValues.value.tree).eqls("z"); - expect(stateVariables["/mi1iva"].stateValues.value.tree).eqls("a"); - expect(stateVariables["/mi2iva"].stateValues.value.tree).eqls("z"); - expect(stateVariables["/mi3iva"].stateValues.value.tree).eqls("a"); - expect(stateVariables["/mi4iva"].stateValues.value.tree).eqls("b"); - - expect(stateVariables["/mi1changed"].stateValues.value).eq(true); - expect(stateVariables["/mi2changed"].stateValues.value).eq(true); - expect(stateVariables["/mi3changed"].stateValues.value).eq(true); - expect(stateVariables["/mi4changed"].stateValues.value).eq(false); - expect(stateVariables["/mi1ivchanged"].stateValues.value).eq(true); - expect(stateVariables["/mi2ivchanged"].stateValues.value).eq(true); - expect(stateVariables["/mi3ivchanged"].stateValues.value).eq(true); - expect(stateVariables["/mi4ivchanged"].stateValues.value).eq(true); - - // press enter in fourth marks fourth value as changed + await check_items( + [mi1, mi2, mi3, mi4], + [mi1iv, mi2iv, mi3iv, mi4iv], + [mi1changed, mi2changed, mi3changed, mi4changed], + [mi1ivchanged, mi2ivchanged, mi3ivchanged, mi4ivchanged], + ); + // update value in fourth marks fourth value as changed + mi2 = mi2iv = mi4 = mi4iv; + mi4changed = true; await updateMathInputValueToImmediateValue({ componentName: "/mi4", core, }); - stateVariables = await returnAllStateVariables(core); - - expect(stateVariables["/mi1a"].stateValues.value.tree).eqls("a"); - expect(stateVariables["/mi2a"].stateValues.value.tree).eqls("b"); - expect(stateVariables["/mi3a"].stateValues.value.tree).eqls("a"); - expect(stateVariables["/mi4a"].stateValues.value.tree).eqls("b"); - expect(stateVariables["/mi1iva"].stateValues.value.tree).eqls("a"); - expect(stateVariables["/mi2iva"].stateValues.value.tree).eqls("b"); - expect(stateVariables["/mi3iva"].stateValues.value.tree).eqls("a"); - expect(stateVariables["/mi4iva"].stateValues.value.tree).eqls("b"); - expect(stateVariables["/mi1changed"].stateValues.value).eq(true); - expect(stateVariables["/mi2changed"].stateValues.value).eq(true); - expect(stateVariables["/mi3changed"].stateValues.value).eq(true); - expect(stateVariables["/mi4changed"].stateValues.value).eq(true); - expect(stateVariables["/mi1ivchanged"].stateValues.value).eq(true); - expect(stateVariables["/mi2ivchanged"].stateValues.value).eq(true); - expect(stateVariables["/mi3ivchanged"].stateValues.value).eq(true); - expect(stateVariables["/mi4ivchanged"].stateValues.value).eq(true); + await check_items( + [mi1, mi2, mi3, mi4], + [mi1iv, mi2iv, mi3iv, mi4iv], + [mi1changed, mi2changed, mi3changed, mi4changed], + [mi1ivchanged, mi2ivchanged, mi3ivchanged, mi4ivchanged], + ); // reload @@ -8883,130 +8874,93 @@ describe("MathInput tag tests", async () => { doenetML, }); - stateVariables = await returnAllStateVariables(core); - expect(stateVariables["/mi1a"].stateValues.value.tree).eqls("\uff3f"); - expect(stateVariables["/mi2a"].stateValues.value.tree).eqls("x"); - expect(stateVariables["/mi3a"].stateValues.value.tree).eqls("\uff3f"); - expect(stateVariables["/mi4a"].stateValues.value.tree).eqls("x"); - expect(stateVariables["/mi1iva"].stateValues.value.tree).eqls("\uff3f"); - expect(stateVariables["/mi2iva"].stateValues.value.tree).eqls("x"); - expect(stateVariables["/mi3iva"].stateValues.value.tree).eqls("\uff3f"); - expect(stateVariables["/mi4iva"].stateValues.value.tree).eqls("x"); - - expect(stateVariables["/mi1changed"].stateValues.value).eq(false); - expect(stateVariables["/mi2changed"].stateValues.value).eq(false); - expect(stateVariables["/mi3changed"].stateValues.value).eq(false); - expect(stateVariables["/mi4changed"].stateValues.value).eq(false); - expect(stateVariables["/mi1ivchanged"].stateValues.value).eq(false); - expect(stateVariables["/mi2ivchanged"].stateValues.value).eq(false); - expect(stateVariables["/mi3ivchanged"].stateValues.value).eq(false); - expect(stateVariables["/mi4ivchanged"].stateValues.value).eq(false); + mi1 = "\uff3f"; + mi2 = "x"; + mi3 = "\uff3f"; + mi4 = "x"; + mi1iv = "\uff3f"; + mi2iv = "x"; + mi3iv = "\uff3f"; + mi4iv = "x"; + mi1changed = false; + mi2changed = false; + mi3changed = false; + mi4changed = false; + mi1ivchanged = false; + mi2ivchanged = false; + mi3ivchanged = false; + mi4ivchanged = false; + + await check_items( + [mi1, mi2, mi3, mi4], + [mi1iv, mi2iv, mi3iv, mi4iv], + [mi1changed, mi2changed, mi3changed, mi4changed], + [mi1ivchanged, mi2ivchanged, mi3ivchanged, mi4ivchanged], + ); // type in third marks only third immediate value as changed - + mi3iv = "y"; + mi3ivchanged = true; await updateMathInputImmediateValue({ - latex: "y", + latex: mi3iv, componentName: "/mi3", core, }); - stateVariables = await returnAllStateVariables(core); - - expect(stateVariables["/mi1a"].stateValues.value.tree).eqls("\uff3f"); - expect(stateVariables["/mi2a"].stateValues.value.tree).eqls("x"); - expect(stateVariables["/mi3a"].stateValues.value.tree).eqls("\uff3f"); - expect(stateVariables["/mi4a"].stateValues.value.tree).eqls("x"); - expect(stateVariables["/mi1iva"].stateValues.value.tree).eqls("\uff3f"); - expect(stateVariables["/mi2iva"].stateValues.value.tree).eqls("x"); - expect(stateVariables["/mi3iva"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi4iva"].stateValues.value.tree).eqls("x"); - - expect(stateVariables["/mi1changed"].stateValues.value).eq(false); - expect(stateVariables["/mi2changed"].stateValues.value).eq(false); - expect(stateVariables["/mi3changed"].stateValues.value).eq(false); - expect(stateVariables["/mi4changed"].stateValues.value).eq(false); - expect(stateVariables["/mi1ivchanged"].stateValues.value).eq(false); - expect(stateVariables["/mi2ivchanged"].stateValues.value).eq(false); - expect(stateVariables["/mi3ivchanged"].stateValues.value).eq(true); - expect(stateVariables["/mi4ivchanged"].stateValues.value).eq(false); + await check_items( + [mi1, mi2, mi3, mi4], + [mi1iv, mi2iv, mi3iv, mi4iv], + [mi1changed, mi2changed, mi3changed, mi4changed], + [mi1ivchanged, mi2ivchanged, mi3ivchanged, mi4ivchanged], + ); - // press enter in third marks first and third value/immediateValue as changed + // update value in third marks first and third value/immediateValue as changed + mi1 = mi1iv = mi3 = mi3iv; + mi1changed = true; + mi1ivchanged = true; + mi3changed = true; await updateMathInputValueToImmediateValue({ componentName: "/mi3", core, }); - stateVariables = await returnAllStateVariables(core); - - expect(stateVariables["/mi1a"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi2a"].stateValues.value.tree).eqls("x"); - expect(stateVariables["/mi3a"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi4a"].stateValues.value.tree).eqls("x"); - expect(stateVariables["/mi1iva"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi2iva"].stateValues.value.tree).eqls("x"); - expect(stateVariables["/mi3iva"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi4iva"].stateValues.value.tree).eqls("x"); - - expect(stateVariables["/mi1changed"].stateValues.value).eq(true); - expect(stateVariables["/mi2changed"].stateValues.value).eq(false); - expect(stateVariables["/mi3changed"].stateValues.value).eq(true); - expect(stateVariables["/mi4changed"].stateValues.value).eq(false); - expect(stateVariables["/mi1ivchanged"].stateValues.value).eq(true); - expect(stateVariables["/mi2ivchanged"].stateValues.value).eq(false); - expect(stateVariables["/mi3ivchanged"].stateValues.value).eq(true); - expect(stateVariables["/mi4ivchanged"].stateValues.value).eq(false); + await check_items( + [mi1, mi2, mi3, mi4], + [mi1iv, mi2iv, mi3iv, mi4iv], + [mi1changed, mi2changed, mi3changed, mi4changed], + [mi1ivchanged, mi2ivchanged, mi3ivchanged, mi4ivchanged], + ); // type in fourth marks only fourth immediate value as changed + mi4iv = "z"; + mi4ivchanged = true; await updateMathInputImmediateValue({ - latex: "z", + latex: mi4iv, componentName: "/mi4", core, }); - stateVariables = await returnAllStateVariables(core); - - expect(stateVariables["/mi1a"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi2a"].stateValues.value.tree).eqls("x"); - expect(stateVariables["/mi3a"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi4a"].stateValues.value.tree).eqls("x"); - expect(stateVariables["/mi1iva"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi2iva"].stateValues.value.tree).eqls("x"); - expect(stateVariables["/mi3iva"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi4iva"].stateValues.value.tree).eqls("z"); - - expect(stateVariables["/mi1changed"].stateValues.value).eq(true); - expect(stateVariables["/mi2changed"].stateValues.value).eq(false); - expect(stateVariables["/mi3changed"].stateValues.value).eq(true); - expect(stateVariables["/mi4changed"].stateValues.value).eq(false); - expect(stateVariables["/mi1ivchanged"].stateValues.value).eq(true); - expect(stateVariables["/mi2ivchanged"].stateValues.value).eq(false); - expect(stateVariables["/mi3ivchanged"].stateValues.value).eq(true); - expect(stateVariables["/mi4ivchanged"].stateValues.value).eq(true); - - // press enter in fourth marks third and fourth value/immediateValue as changed + await check_items( + [mi1, mi2, mi3, mi4], + [mi1iv, mi2iv, mi3iv, mi4iv], + [mi1changed, mi2changed, mi3changed, mi4changed], + [mi1ivchanged, mi2ivchanged, mi3ivchanged, mi4ivchanged], + ); + // update value in fourth marks third and fourth value/immediateValue as changed + mi2 = mi2iv = mi4 = mi4iv; + mi2changed = true; + mi2ivchanged = true; + mi4changed = true; await updateMathInputValueToImmediateValue({ componentName: "/mi4", core, }); - stateVariables = await returnAllStateVariables(core); - - expect(stateVariables["/mi1a"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi2a"].stateValues.value.tree).eqls("z"); - expect(stateVariables["/mi3a"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi4a"].stateValues.value.tree).eqls("z"); - expect(stateVariables["/mi1iva"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi2iva"].stateValues.value.tree).eqls("z"); - expect(stateVariables["/mi3iva"].stateValues.value.tree).eqls("y"); - expect(stateVariables["/mi4iva"].stateValues.value.tree).eqls("z"); - - expect(stateVariables["/mi1changed"].stateValues.value).eq(true); - expect(stateVariables["/mi2changed"].stateValues.value).eq(true); - expect(stateVariables["/mi3changed"].stateValues.value).eq(true); - expect(stateVariables["/mi4changed"].stateValues.value).eq(true); - expect(stateVariables["/mi1ivchanged"].stateValues.value).eq(true); - expect(stateVariables["/mi2ivchanged"].stateValues.value).eq(true); - expect(stateVariables["/mi3ivchanged"].stateValues.value).eq(true); - expect(stateVariables["/mi4ivchanged"].stateValues.value).eq(true); + await check_items( + [mi1, mi2, mi3, mi4], + [mi1iv, mi2iv, mi3iv, mi4iv], + [mi1changed, mi2changed, mi3changed, mi4changed], + [mi1ivchanged, mi2ivchanged, mi3ivchanged, mi4ivchanged], + ); }); it("math input with label", async () => { @@ -9222,4 +9176,202 @@ describe("MathInput tag tests", async () => { expect(stateVariables["/mi2iv"].stateValues.value.tree).eq(1); expect(stateVariables["/mi2rv"].stateValues.value).eq("1"); }); + + it("mathInputs specifying point", async () => { + // two mathInputs specifying the x and y coordinate of a single point + // demonstrates two-way data binding + + let core = await createTestCore({ + doenetML: ` + + + + ($x,$y) + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/x"].stateValues.value.tree).eq(1); + expect(stateVariables["/y"].stateValues.value.tree).eq(2); + expect(stateVariables["/P"].stateValues.xs[0].tree).eq(1); + expect(stateVariables["/P"].stateValues.xs[1].tree).eq(2); + + // Enter -3 for x + await updateMathInputValue({ latex: "-3", componentName: "/x", core }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/x"].stateValues.value.tree).eq(-3); + expect(stateVariables["/y"].stateValues.value.tree).eq(2); + expect(stateVariables["/P"].stateValues.xs[0].tree).eq(-3); + expect(stateVariables["/P"].stateValues.xs[1].tree).eq(2); + + // Enter -4 for y + await updateMathInputValue({ latex: "-4", componentName: "/y", core }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/x"].stateValues.value.tree).eq(-3); + expect(stateVariables["/y"].stateValues.value.tree).eq(-4); + expect(stateVariables["/P"].stateValues.xs[0].tree).eq(-3); + expect(stateVariables["/P"].stateValues.xs[1].tree).eq(-4); + + // move point to (5,-6) + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 5, y: -6 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/x"].stateValues.value.tree).eq(5); + expect(stateVariables["/y"].stateValues.value.tree).eq(-6); + expect(stateVariables["/P"].stateValues.xs[0].tree).eq(5); + expect(stateVariables["/P"].stateValues.xs[1].tree).eq(-6); + }); + + it("mathInput specifying point -- non-invertible x", async () => { + // x-coordinate is the square of the first mathInput + // therefore, cannot invert from x-coordinate to mathInput + // so that cannot change x-coordinate directly by dragging point + + let core = await createTestCore({ + doenetML: ` + + + + ($x^2,$y) + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/x"].stateValues.value.tree).eq(3); + expect(stateVariables["/y"].stateValues.value.tree).eq(2); + expect(stateVariables["/P"].stateValues.xs[0].tree).eq(9); + expect(stateVariables["/P"].stateValues.xs[1].tree).eq(2); + + // Enter -1.2 for x + await updateMathInputValue({ + latex: "-1.2", + componentName: "/x", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/x"].stateValues.value.tree).eq(-1.2); + expect(stateVariables["/y"].stateValues.value.tree).eq(2); + expect(stateVariables["/P"].stateValues.xs[0].tree).eq(1.44); + expect(stateVariables["/P"].stateValues.xs[1].tree).eq(2); + + // try to move point to (5,6), only y changes + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 5, y: 6 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/x"].stateValues.value.tree).eq(-1.2); + expect(stateVariables["/y"].stateValues.value.tree).eq(6); + expect(stateVariables["/P"].stateValues.xs[0].tree).eq(1.44); + expect(stateVariables["/P"].stateValues.xs[1].tree).eq(6); + }); + + it("mathInput specifying point -- product", async () => { + // x-coordinate of a point is product of mathInputs + // Since cannot determine both factors from the product + // the transformation is non-invertible + // and cannot directly change the x-coordinate of point by dragging + + let core = await createTestCore({ + doenetML: ` + + + + ($a$b, -7) + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a"].stateValues.value.tree).eq(-3); + expect(stateVariables["/b"].stateValues.value.tree).eq(2); + expect(stateVariables["/P"].stateValues.xs[0].tree).eq(-6); + expect(stateVariables["/P"].stateValues.xs[1].tree).eq(-7); + + // Enter -1.5 for a + await updateMathInputValue({ + latex: "-1.5", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a"].stateValues.value.tree).eq(-1.5); + expect(stateVariables["/b"].stateValues.value.tree).eq(2); + expect(stateVariables["/P"].stateValues.xs[0].tree).eq(-3); + expect(stateVariables["/P"].stateValues.xs[1].tree).eq(-7); + + // try to move point to (5,6), only y changes + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 5, y: 6 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a"].stateValues.value.tree).eq(-1.5); + expect(stateVariables["/b"].stateValues.value.tree).eq(2); + expect(stateVariables["/P"].stateValues.xs[0].tree).eq(-3); + expect(stateVariables["/P"].stateValues.xs[1].tree).eq(6); + }); + + it("mathInput specifying point -- product, make invertible", async () => { + // x-coordinate of a point is product of mathInputs + // Since one factor is marked with modifyIndirectly=false, + // we leave that factor constant when changing the x-coordinate by dragging + // and modify the other factor to match the new x-coordinate + + let core = await createTestCore({ + doenetML: ` + + + + ($a$b{modifyIndirectly="false"}, -7) + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a"].stateValues.value.tree).eq(-3); + expect(stateVariables["/b"].stateValues.value.tree).eq(2); + expect(stateVariables["/P"].stateValues.xs[0].tree).eq(-6); + expect(stateVariables["/P"].stateValues.xs[1].tree).eq(-7); + + // Enter -1.5 for a + await updateMathInputValue({ + latex: "-1.5", + componentName: "/a", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a"].stateValues.value.tree).eq(-1.5); + expect(stateVariables["/b"].stateValues.value.tree).eq(2); + expect(stateVariables["/P"].stateValues.xs[0].tree).eq(-3); + expect(stateVariables["/P"].stateValues.xs[1].tree).eq(-7); + + // try to move point to (5,6) + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 5, y: 6 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/a"].stateValues.value.tree).eqls(["/", 5, 2]); + expect(stateVariables["/b"].stateValues.value.tree).eq(2); + expect(stateVariables["/P"].stateValues.xs[0].tree).eq(5); + expect(stateVariables["/P"].stateValues.xs[1].tree).eq(6); + }); }); diff --git a/packages/doenetml-worker/src/test/tagSpecific/number.test.ts b/packages/doenetml-worker/src/test/tagSpecific/number.test.ts index b87a8bcfa..1516d0059 100644 --- a/packages/doenetml-worker/src/test/tagSpecific/number.test.ts +++ b/packages/doenetml-worker/src/test/tagSpecific/number.test.ts @@ -1786,7 +1786,6 @@ describe("Number tag tests", async () => {

Content 2: $number2

Content 1

Content 2

-

`, }); diff --git a/packages/doenetml-worker/src/test/tagSpecific/sampleprimenumbers.test.ts b/packages/doenetml-worker/src/test/tagSpecific/sampleprimenumbers.test.ts new file mode 100644 index 000000000..aee95084a --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/sampleprimenumbers.test.ts @@ -0,0 +1,607 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { updateMathInputValue } from "../utils/actions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +describe("SamplePrimeNumbers tag tests", async () => { + async function test_values_separately({ + doenetML, + componentNames, + compositeName, + valid_values, + num_samples, + must_be_distinct = false, + is_math = false, + }: { + doenetML: string; + componentNames: string[]; + compositeName?: string; + valid_values: any[][]; + num_samples: number; + must_be_distinct?: boolean; + is_math?: boolean; + }) { + for (let i = 0; i < num_samples; i++) { + let core = await createTestCore({ + doenetML, + requestedVariantIndex: i, + }); + const stateVariables = await returnAllStateVariables(core); + const s = stateVariables[compositeName ?? ""]; + for (let [ind, name] of componentNames.entries()) { + let value = name + ? stateVariables[name].stateValues.value + : stateVariables[s.replacements![ind].componentName] + .stateValues.value; + expect( + is_math + ? valid_values[ind].some((v) => v.equals(value)) + : valid_values[ind].includes(value), + ).eq(true, `Expected ${value} to be in ${valid_values[ind]}`); + } + + if (must_be_distinct) { + for (let name1 of componentNames) { + let val1 = stateVariables[name1].stateValues.value; + for (let name2 of componentNames) { + if (name2 !== name1) { + let val2 = stateVariables[name2].stateValues.value; + if (is_math) { + expect(val2.equals(val1)).eq(false); + } else { + expect(val2).not.eq(val1); + } + } + } + } + } + } + } + + async function test_combined_values({ + doenetML, + componentNames, + valid_combinations, + num_samples, + is_math = false, + }: { + doenetML: string; + componentNames: string[]; + valid_combinations: any[][]; + num_samples: number; + is_math?: boolean; + }) { + for (let i = 0; i < num_samples; i++) { + let core = await createTestCore({ + doenetML, + requestedVariantIndex: i, + }); + const stateVariables = await returnAllStateVariables(core); + let values = componentNames.map( + (name) => stateVariables[name].stateValues.value, + ); + + expect( + valid_combinations.some((comb) => + comb.every((v, i) => + is_math ? v.equals(values[i]) : v === values[i], + ), + ), + ).eq( + true, + `Expected (${values}) to be in ${valid_combinations.map((comb) => `(${comb})`)}`, + ); + } + } + + it("sample five prime numbers up to 20, only maxValue specified", async () => { + const doenetML = ``; + const values = [2, 3, 5, 7, 11, 13, 17, 19]; + const valid_values = Array(5).fill(values); + const componentNames = ["/res1", "/res2", "/res3", "/res4", "/res5"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 10, + }); + }); + + it("sample five prime numbers between 50 and 100, only minValue specified", async () => { + const doenetML = ``; + const values = [53, 59, 61, 67, 71, 73, 79, 83, 89, 97]; + const valid_values = Array(5).fill(values); + const componentNames = ["/res1", "/res2", "/res3", "/res4", "/res5"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 10, + }); + }); + + it("sample fifty prime numbers between 10,000 and 100,0000", async () => { + let core = await createTestCore({ + doenetML: ``, + }); + + let stateVariables = await returnAllStateVariables(core); + + let samples = stateVariables["/s"].replacements!.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + expect(samples.length).eq(50); + + for (let sample of samples) { + expect( + Number.isInteger(sample) && sample >= 10000 && sample <= 100000, + ).eq(true); + + let isPrime = true; + let sqrtSample = Math.sqrt(sample); + for (let i = 2; i <= sqrtSample; i++) { + if (sample % i === 0) { + isPrime = false; + break; + } + } + + expect(isPrime).eq(true); + } + }); + + it("sample fifty prime numbers between 1900 and 2000, excluding 1931, 1979, and 1997", async () => { + const doenetML = ``; + const values = [ + 1901, 1907, 1913, 1933, 1949, 1951, 1973, 1987, 1993, 1999, + ]; + const valid_values = Array(50).fill(values); + const componentNames = [ + "/res1", + "/res2", + "/res3", + "/res4", + "/res5", + ...Array(45).fill(""), + ]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + compositeName: "/s", + num_samples: 1, + }); + }); + + it("sampled numbers do change dynamically", async () => { + let core = await createTestCore({ + doenetML: ` + + +

+ +

+ + + + $exclude +

+ +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let sample1replacements = stateVariables["/sample1"].replacements!; + let sample2replacements = stateVariables["/sample2"].replacements!; + expect(sample1replacements.length).eq(50); + expect(sample2replacements.length).eq(180); + let sample1numbers = sample1replacements.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let sample2numbers = sample2replacements.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + + for (let num of sample1numbers) { + expect([2, 3, 5, 7].includes(num)).eq(true); + } + for (let num of sample2numbers) { + expect([2, 3, 5, 11, 13, 17, 23, 31, 41, 43].includes(num)).eq( + true, + ); + } + + // Get new samples when change number of samples + await updateMathInputValue({ + latex: "70", + componentName: "/numSamples", + core, + }); + await updateMathInputValue({ + latex: "160", + componentName: "/numSamples2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + let sample1numbersb = stateVariables["/sample1"].replacements!.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let sample2numbersb = stateVariables["/sample2"] + .replacements!.slice( + 0, + stateVariables["/sample2"].replacements!.length - + (stateVariables["/sample2"].replacementsToWithhold ?? 0), + ) + .map((x) => stateVariables[x.componentName].stateValues.value); + expect(sample1numbersb.length).eq(70); + expect(sample2numbersb.length).eq(160); + + for (let num of sample1numbersb) { + expect([2, 3, 5, 7].includes(num)).eq(true); + } + + for (let num of sample2numbersb) { + expect([2, 3, 5, 11, 13, 17, 23, 31, 41, 43].includes(num)).eq( + true, + ); + } + + expect(sample1numbersb.slice(0, 10)).not.eqls( + sample1numbers.slice(0, 10), + ); + expect(sample2numbersb.slice(0, 10)).not.eqls( + sample2numbers.slice(0, 10), + ); + + // Get new samples when change parameters + await updateMathInputValue({ + latex: "20", + componentName: "/maxNum", + core, + }); + await updateMathInputValue({ + latex: "7, 19, 29, 37, 47, 2, 11, 23, 31, 41", + componentName: "/exclude", + core, + }); + + stateVariables = await returnAllStateVariables(core); + let sample1numbersc = stateVariables["/sample1"].replacements!.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let sample2numbersc = stateVariables["/sample2"] + .replacements!.slice( + 0, + stateVariables["/sample2"].replacements!.length - + (stateVariables["/sample2"].replacementsToWithhold ?? 0), + ) + .map((x) => stateVariables[x.componentName].stateValues.value); + expect(sample1numbersc.length).eq(70); + expect(sample2numbersc.length).eq(160); + + for (let num of sample1numbersc) { + expect([2, 3, 5, 7, 11, 13, 17, 19].includes(num)).eq(true); + } + + for (let num of sample2numbersc) { + expect([3, 5, 13, 17, 43].includes(num)).eq(true); + } + + expect(sample1numbersc.slice(0, 10)).not.eqls( + sample1numbersb.slice(0, 10), + ); + expect(sample2numbersc.slice(0, 10)).not.eqls( + sample2numbersb.slice(0, 10), + ); + }); + + it("sampled numbers don't resample in dynamic map", async () => { + let core = await createTestCore({ + doenetML: ` + How many numbers do you want? +

+ + + + +

+ +

$map1

+ + $p1{name="p3"} + $p2{name="p4"} + + $p3{name="p5"} + $p4{name="p6"} + `, + }); + + async function check_sampled_numbers(sampledNumbers: number[]) { + const stateVariables = await returnAllStateVariables(core); + + expect( + stateVariables["/p1"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + + expect( + stateVariables["/p2"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + + expect( + stateVariables["/p3"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + + expect( + stateVariables["/p4"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + + expect( + stateVariables["/p5"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + + expect( + stateVariables["/p6"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + } + + let sampledNumbers: number[] = []; + + // initially nothing + await check_sampled_numbers([]); + + // sample one variable + await updateMathInputValue({ latex: "1", componentName: "/mi1", core }); + + let stateVariables = await returnAllStateVariables(core); + sampledNumbers.push(stateVariables["/a/n"].stateValues.value); + await check_sampled_numbers(sampledNumbers); + + // go back to nothing + await updateMathInputValue({ latex: "0", componentName: "/mi1", core }); + await check_sampled_numbers([]); + + // get same number back + await updateMathInputValue({ latex: "1", componentName: "/mi1", core }); + await check_sampled_numbers(sampledNumbers); + + // get two more samples + await updateMathInputValue({ latex: "3", componentName: "/mi1", core }); + + stateVariables = await returnAllStateVariables(core); + let n1 = stateVariables["/a/n"].stateValues.value; + let n2 = stateVariables["/b/n"].stateValues.value; + let n3 = stateVariables["/c/n"].stateValues.value; + expect(n1).eq(sampledNumbers[0]); + sampledNumbers.push(n2); + sampledNumbers.push(n3); + await check_sampled_numbers(sampledNumbers); + + // go back to nothing + await updateMathInputValue({ latex: "0", componentName: "/mi1", core }); + await check_sampled_numbers([]); + + // get first two numbers back + await updateMathInputValue({ latex: "2", componentName: "/mi1", core }); + await check_sampled_numbers(sampledNumbers.slice(0, 2)); + + // get six total samples + await updateMathInputValue({ latex: "6", componentName: "/mi1", core }); + + stateVariables = await returnAllStateVariables(core); + n1 = stateVariables["/a/n"].stateValues.value; + n2 = stateVariables["/b/n"].stateValues.value; + n3 = stateVariables["/c/n"].stateValues.value; + let n4 = stateVariables["/d/n"].stateValues.value; + let n5 = stateVariables["/e/n"].stateValues.value; + let n6 = stateVariables["/f/n"].stateValues.value; + expect(n1).eq(sampledNumbers[0]); + expect(n2).eq(sampledNumbers[1]); + expect(n3).eq(sampledNumbers[2]); + sampledNumbers.push(n4); + sampledNumbers.push(n5); + sampledNumbers.push(n6); + await check_sampled_numbers(sampledNumbers); + + // go back to nothing + await updateMathInputValue({ latex: "0", componentName: "/mi1", core }); + await check_sampled_numbers([]); + + // get all six back + await updateMathInputValue({ latex: "6", componentName: "/mi1", core }); + await check_sampled_numbers(sampledNumbers); + }); + + it("asList", async () => { + let core = await createTestCore({ + doenetML: ` +

+

+ `, + }); + + let results: number[] = []; + + let stateVariables = await returnAllStateVariables(core); + + results.push(stateVariables["/u"].stateValues.value); + results.push(stateVariables["/v"].stateValues.value); + results.push(stateVariables["/w"].stateValues.value); + results.push(stateVariables["/x"].stateValues.value); + results.push(stateVariables["/y"].stateValues.value); + + for (let num of results) { + expect([179, 181, 191, 193, 197, 199].includes(num)); + } + expect(stateVariables["/p1"].stateValues.text).eq(results.join(", ")); + expect(stateVariables["/p2"].stateValues.text).eq(results.join("")); + }); + + it("same numbers for given variant if variantDeterminesSeed", async () => { + let doenetML = ` +

+ + +

+ + `; + + let core = await createTestCore({ + doenetML, + requestedVariantIndex: 1, + }); + + let stateVariables = await returnAllStateVariables(core); + + let samples = stateVariables["/p1"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + + expect(samples.length).eq(100); + + for (let sample of samples) { + expect( + [ + 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, + 59, 61, 67, 71, 73, 79, 83, 89, 97, + ].includes(sample), + ).eq(true); + } + + core = await createTestCore({ + doenetML, + requestedVariantIndex: 1, + }); + + stateVariables = await returnAllStateVariables(core); + + let samples2 = stateVariables["/p1"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + + expect(samples2).eqls(samples); + + core = await createTestCore({ + doenetML, + requestedVariantIndex: 2, + }); + + stateVariables = await returnAllStateVariables(core); + + samples2 = stateVariables["/p1"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + + expect(samples2.length).eq(100); + + for (let sample of samples2) { + expect( + [ + 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, + 59, 61, 67, 71, 73, 79, 83, 89, 97, + ].includes(sample), + ).eq(true); + } + + expect(samples2).not.eqls(samples); + }); + + it(`resample prime numbers`, async () => { + let core = await createTestCore({ + doenetML: ` +

, + +

+ +

+ + +

+ + `, + }); + + let pn1, pn2, pn3; + let pn1b, pn2b, pn3b; + + let stateVariables = await returnAllStateVariables(core); + + pn1 = stateVariables["/pn1"].stateValues.value; + pn2 = stateVariables["/pn2"].stateValues.value; + pn3 = stateVariables["/pn3"].stateValues.value; + + expect(pn1).gt(1).lt(1000); + expect(pn2).gt(1).lt(1000); + expect(pn3).gt(1000).lt(10000); + + expect(stateVariables["/pn1"].stateValues.text).eq(pn1.toString()); + + await core.requestAction({ + componentName: "/resamp1", + actionName: "callAction", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + pn1b = stateVariables["/pn1"].stateValues.value; + pn2b = stateVariables["/pn2"].stateValues.value; + pn3b = stateVariables["/pn3"].stateValues.value; + + expect(pn1b).gt(1).lt(1000); + expect(pn2b).gt(1).lt(1000); + expect(pn3b).gt(1000).lt(10000); + + expect(pn1b).not.eq(pn1); + expect(pn2b).not.eq(pn2); + expect(pn3b).eq(pn3); + + expect(stateVariables["/pn3"].stateValues.text).eq(pn3.toString()); + + await core.requestAction({ + componentName: "/resamp2", + actionName: "callAction", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + let pn1c = stateVariables["/pn1"].stateValues.value; + let pn2c = stateVariables["/pn2"].stateValues.value; + let pn3c = stateVariables["/pn3"].stateValues.value; + + expect(pn1c).gt(1).lt(1000); + expect(pn2c).gt(1).lt(1000); + expect(pn3c).gt(1000).lt(10000); + + expect(pn1c).eq(pn1b); + expect(pn2c).eq(pn2b); + expect(pn3c).not.eq(pn3); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/select.test.ts b/packages/doenetml-worker/src/test/tagSpecific/select.test.ts new file mode 100644 index 000000000..9f091547d --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/select.test.ts @@ -0,0 +1,3278 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { + updateBooleanInputValue, + updateMathInputValue, +} from "../utils/actions"; +import me from "math-expressions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +describe("Select tag tests", async () => { + async function test_values_separately({ + doenetML, + componentNames, + selectName, + valid_values, + num_samples, + must_be_distinct = false, + is_math = false, + }: { + doenetML: string; + componentNames: string[]; + selectName?: string; + valid_values: any[][]; + num_samples: number; + must_be_distinct?: boolean; + is_math?: boolean; + }) { + for (let i = 0; i < num_samples; i++) { + let core = await createTestCore({ + doenetML, + requestedVariantIndex: i, + }); + const stateVariables = await returnAllStateVariables(core); + const s = stateVariables[selectName ?? ""]; + for (let [ind, name] of componentNames.entries()) { + let value = name + ? stateVariables[name].stateValues.value + : stateVariables[ + stateVariables[s.replacements![ind].componentName] + .replacements![0].componentName + ].stateValues.value; + expect( + is_math + ? valid_values[ind].some((v) => v.equals(value)) + : valid_values[ind].includes(value), + ).eq(true, `Expected ${value} to be in ${valid_values[ind]}`); + } + + if (must_be_distinct) { + for (let name1 of componentNames) { + let val1 = stateVariables[name1].stateValues.value; + for (let name2 of componentNames) { + if (name2 !== name1) { + let val2 = stateVariables[name2].stateValues.value; + if (is_math) { + expect(val2.equals(val1)).eq(false); + } else { + expect(val2).not.eq(val1); + } + } + } + } + } + } + } + + async function test_combined_values({ + doenetML, + componentNames, + valid_combinations, + num_samples, + is_math = false, + }: { + doenetML: string; + componentNames: string[]; + valid_combinations: any[][]; + num_samples: number; + is_math?: boolean; + }) { + for (let i = 0; i < num_samples; i++) { + let core = await createTestCore({ + doenetML, + requestedVariantIndex: i, + }); + const stateVariables = await returnAllStateVariables(core); + let values = componentNames.map( + (name) => stateVariables[name].stateValues.value, + ); + + expect( + valid_combinations.some((comb) => + comb.every((v, i) => + is_math ? v.equals(values[i]) : v === values[i], + ), + ), + ).eq( + true, + `Expected (${values}) to be in ${valid_combinations.map((comb) => `(${comb})`)}`, + ); + } + } + + it("no parameters, select doesn't do anything", async () => { + let core = await createTestCore({ + doenetML: ` +

+ + + + + + + `; + const valid_values = [ + [ + me.fromText("u"), + me.fromText("v"), + me.fromText("w"), + me.fromText("x"), + me.fromText("y"), + me.fromText("z"), + ], + ]; + const componentNames = ["/res"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 10, + is_math: true, + }); + }); + + it("select multiple maths", async () => { + const doenetML = ` + `; + + const vals = [ + me.fromText("u"), + me.fromText("v"), + me.fromText("w"), + me.fromText("x"), + me.fromText("y"), + me.fromText("z"), + ]; + const valid_values = Array(3).fill(vals); + const componentNames = ["/res1", "/res2", "/res3"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 10, + is_math: true, + must_be_distinct: true, + }); + }); + + it("select multiple maths, initially unresolved", async () => { + const doenetML = ` + + + $n3{name="n2"} + $num1{name="n"} + $n2+$num2 + $n3+$num3 + $num3{name="n3"} + 1`; + const valid_values = [ + [ + me.fromText("u"), + me.fromText("v"), + me.fromText("w"), + me.fromText("x"), + me.fromText("y"), + me.fromText("z"), + ], + [ + me.fromText("u"), + me.fromText("v"), + me.fromText("w"), + me.fromText("x"), + me.fromText("y"), + me.fromText("z"), + ], + [ + me.fromText("u"), + me.fromText("v"), + me.fromText("w"), + me.fromText("x"), + me.fromText("y"), + me.fromText("z"), + ], + ]; + const componentNames = ["/res1", "/res2", "/res3"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 10, + is_math: true, + must_be_distinct: true, + }); + }); + + it("select multiple maths with namespace", async () => { + const doenetML = ` + `; + const vals = [ + me.fromText("u"), + me.fromText("v"), + me.fromText("w"), + me.fromText("x"), + me.fromText("y"), + me.fromText("z"), + ]; + const valid_values = Array(3).fill(vals); + const componentNames = ["/s/res1", "/s/res2", "/s/res3"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 10, + is_math: true, + must_be_distinct: true, + }); + }); + + it("select multiple maths, with replacement", async () => { + const doenetML = ` + `; + const vals = [ + me.fromText("u"), + me.fromText("v"), + me.fromText("w"), + me.fromText("x"), + me.fromText("y"), + me.fromText("z"), + ]; + const valid_values = Array(5).fill(vals); + const componentNames = ["/res1", "/res2", "/res3", "", ""]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + selectName: "/s", + num_samples: 10, + is_math: true, + }); + }); + + it("asList", async () => { + let core = await createTestCore({ + doenetML: ` +

+

1 2 3 4 5 6 7 + +

+ +

+ $sample1{name="noresample1"} + $sample2{name="noresample2"} + $noresample1{name="noreresample1"} + $noresample2{name="noreresample2"} +

+ +

+ +

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + let num1 = stateVariables["/n1"].stateValues.value; + let num2 = stateVariables["/n2"].stateValues.value; + expect(Number.isInteger(num1) && num1 >= 1 && num1 <= 7).eq(true); + expect(Number.isInteger(num2) && num2 >= 1 && num2 <= 7).eq(true); + expect( + stateVariables[ + stateVariables[ + stateVariables["/noresample1"].replacements![0] + .componentName + ].replacements![0].componentName + ].stateValues.value, + ).eq(num1); + expect( + stateVariables[ + stateVariables[ + stateVariables["/noresample2"].replacements![0] + .componentName + ].replacements![0].componentName + ].stateValues.value, + ).eq(num2); + expect( + stateVariables[ + stateVariables[ + stateVariables["/noreresample1"].replacements![0] + .componentName + ].replacements![0].componentName + ].stateValues.value, + ).eq(num1); + expect( + stateVariables[ + stateVariables[ + stateVariables["/noreresample2"].replacements![0] + .componentName + ].replacements![0].componentName + ].stateValues.value, + ).eq(num2); + + expect( + stateVariables[ + stateVariables["/noresamplep"].activeChildren[1].componentName + ].stateValues.value, + ).eq(num1); + expect( + stateVariables[ + stateVariables["/noresamplep"].activeChildren[3].componentName + ].stateValues.value, + ).eq(num2); + expect( + stateVariables[ + stateVariables["/noreresamplep"].activeChildren[1].componentName + ].stateValues.value, + ).eq(num1); + expect( + stateVariables[ + stateVariables["/noreresamplep"].activeChildren[3].componentName + ].stateValues.value, + ).eq(num2); + }); + + it("select doesn't change dynamically", async () => { + let core = await createTestCore({ + doenetML: ` + + + + +

+ +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let sampleReplacements = stateVariables["/sample1"].replacements!; + expect(sampleReplacements.length).eq(5); + + let sampleMaths = sampleReplacements.map( + (x) => + stateVariables[ + stateVariables[ + stateVariables[x.componentName].replacements![0] + .componentName + ].replacements![0].componentName + ].stateValues.value.tree, + ); + + for (let val of sampleMaths) { + expect(["a", "b", "c"].includes(val)).eq(true); + } + + // Nothing changes when change number to select + await updateMathInputValue({ + latex: "7", + componentName: "/numToSelect", + core, + }); + + stateVariables = await returnAllStateVariables(core); + sampleReplacements = stateVariables["/sample1"].replacements!; + + expect( + sampleReplacements.map( + (x) => + stateVariables[ + stateVariables[ + stateVariables[x.componentName].replacements![0] + .componentName + ].replacements![0].componentName + ].stateValues.value.tree, + ), + ).eqls(sampleMaths); + + // Values change to reflect copy sources + + let newValues = { + a: "q", + b: "r", + c: "s", + }; + await updateMathInputValue({ + latex: newValues.a, + componentName: "/x", + core, + }); + await updateMathInputValue({ + latex: newValues.b, + componentName: "/y", + core, + }); + await updateMathInputValue({ + latex: newValues.c, + componentName: "/z", + core, + }); + + stateVariables = await returnAllStateVariables(core); + sampleReplacements = stateVariables["/sample1"].replacements!; + + let sampleMaths2 = sampleReplacements.map( + (x) => + stateVariables[ + stateVariables[ + stateVariables[x.componentName].replacements![0] + .componentName + ].replacements![0].componentName + ].stateValues.value.tree, + ); + + expect(sampleMaths2).eqls(sampleMaths.map((x) => newValues[x])); + }); + + it("select doesn't resample in dynamic map", async () => { + let core = await createTestCore({ + doenetML: ` + How many numbers do you want? +

+ + + + +

+ +

$map1

+ + $p1{name="p3"} + $p2{name="p4"} + + $p3{name="p5"} + $p4{name="p6"} + `, + }); + + async function check_sampled_numbers(sampledNumbers: number[]) { + const stateVariables = await returnAllStateVariables(core); + + expect( + stateVariables["/p1"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + + expect( + stateVariables["/p2"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + + expect( + stateVariables["/p3"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + + expect( + stateVariables["/p4"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + + expect( + stateVariables["/p5"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + + expect( + stateVariables["/p6"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + } + + let sampledNumbers: number[] = []; + + // initially nothing + await check_sampled_numbers([]); + + // sample one variable + await updateMathInputValue({ latex: "1", componentName: "/mi1", core }); + + let stateVariables = await returnAllStateVariables(core); + sampledNumbers.push(stateVariables["/a/n"].stateValues.value); + await check_sampled_numbers(sampledNumbers); + + // go back to nothing + await updateMathInputValue({ latex: "0", componentName: "/mi1", core }); + await check_sampled_numbers([]); + + // get same number back + await updateMathInputValue({ latex: "1", componentName: "/mi1", core }); + await check_sampled_numbers(sampledNumbers); + + // get two more samples + await updateMathInputValue({ latex: "3", componentName: "/mi1", core }); + + stateVariables = await returnAllStateVariables(core); + let n1 = stateVariables["/a/n"].stateValues.value; + let n2 = stateVariables["/b/n"].stateValues.value; + let n3 = stateVariables["/c/n"].stateValues.value; + expect(n1).eq(sampledNumbers[0]); + sampledNumbers.push(n2); + sampledNumbers.push(n3); + await check_sampled_numbers(sampledNumbers); + + // go back to nothing + await updateMathInputValue({ latex: "0", componentName: "/mi1", core }); + await check_sampled_numbers([]); + + // get first two numbers back + await updateMathInputValue({ latex: "2", componentName: "/mi1", core }); + await check_sampled_numbers(sampledNumbers.slice(0, 2)); + + // get six total samples + await updateMathInputValue({ latex: "6", componentName: "/mi1", core }); + + stateVariables = await returnAllStateVariables(core); + n1 = stateVariables["/a/n"].stateValues.value; + n2 = stateVariables["/b/n"].stateValues.value; + n3 = stateVariables["/c/n"].stateValues.value; + let n4 = stateVariables["/d/n"].stateValues.value; + let n5 = stateVariables["/e/n"].stateValues.value; + let n6 = stateVariables["/f/n"].stateValues.value; + expect(n1).eq(sampledNumbers[0]); + expect(n2).eq(sampledNumbers[1]); + expect(n3).eq(sampledNumbers[2]); + sampledNumbers.push(n4); + sampledNumbers.push(n5); + sampledNumbers.push(n6); + await check_sampled_numbers(sampledNumbers); + + // go back to nothing + await updateMathInputValue({ latex: "0", componentName: "/mi1", core }); + await check_sampled_numbers([]); + + // get all six back + await updateMathInputValue({ latex: "6", componentName: "/mi1", core }); + await check_sampled_numbers(sampledNumbers); + }); + + it("select single group of maths, assign names to grandchildren", async () => { + const doenetML = ` + `; + + const valid_combinations = [ + ["x", "y", "z"].map((x) => me.fromText(x)), + ["u", "v", "w"].map((x) => me.fromText(x)), + ["a", "b", "c"].map((x) => me.fromText(x)), + ["q", "r", "s"].map((x) => me.fromText(x)), + ]; + const componentNames = ["/res1", "/res2", "/res3"]; + + await test_combined_values({ + doenetML, + valid_combinations, + componentNames, + num_samples: 5, + is_math: true, + }); + }); + + it("select single group of maths, assign names with namespace to grandchildren", async () => { + const doenetML = ` + `; + + const valid_combinations = [ + ["x", "y", "z"].map((x) => me.fromText(x)), + ["u", "v", "w"].map((x) => me.fromText(x)), + ["a", "b", "c"].map((x) => me.fromText(x)), + ["q", "r", "s"].map((x) => me.fromText(x)), + ]; + const componentNames = ["/s/res1", "/s/res2", "/s/res3"]; + + await test_combined_values({ + doenetML, + valid_combinations, + componentNames, + num_samples: 5, + is_math: true, + }); + }); + + it("select multiple group of maths, assign names to grandchildren", async () => { + const doenetML = ` + `; + + const valid_combinations = [ + ["x", "y", "z"].map((x) => me.fromText(x)), + ["u", "v", "w"].map((x) => me.fromText(x)), + ["a", "b", "c"].map((x) => me.fromText(x)), + ["q", "r", "s"].map((x) => me.fromText(x)), + ]; + + const allNames = [ + ["/x1", "/y1", "/z1"], + ["/x2", "/y2", "/z2"], + ["/x3", "/y3", "/z3"], + ]; + + for (let componentNames of allNames) { + await test_combined_values({ + doenetML, + valid_combinations, + componentNames, + num_samples: 4, + is_math: true, + }); + } + }); + + it("references to outside components", async () => { + let core = await createTestCore({ + doenetML: ` + x + y + z + + + + a + b + c + +

Selected options repeated

+ $q{name="q2"} + $r{name="r2"} + $s{name="s2"} + $t{name="t2"} + $u{name="u2"} + + `, + }); + + let option = { + "Option 1: ": me.fromText("3xa"), + "Option 2: ": me.fromText("4yb"), + "Option 3: ": me.fromText("5zc"), + }; + + let stateVariables = await returnAllStateVariables(core); + + let q2 = + stateVariables[stateVariables["/q2"].replacements![0].componentName] + .activeChildren; + let q2string = q2[0]; + let q2math = me.fromAst( + stateVariables[q2[1].componentName].stateValues.value, + ); + expect(q2math.equals(option[q2string])).eq(true); + + let r2 = + stateVariables[stateVariables["/r2"].replacements![0].componentName] + .activeChildren; + let r2string = r2[0]; + let r2math = me.fromAst( + stateVariables[r2[1].componentName].stateValues.value, + ); + expect(r2math.equals(option[r2string])).eq(true); + + let s2 = + stateVariables[stateVariables["/s2"].replacements![0].componentName] + .activeChildren; + let s2string = s2[0]; + let s2math = me.fromAst( + stateVariables[s2[1].componentName].stateValues.value, + ); + expect(s2math.equals(option[s2string])).eq(true); + + let t2 = + stateVariables[stateVariables["/t2"].replacements![0].componentName] + .activeChildren; + let t2string = t2[0]; + let t2math = me.fromAst( + stateVariables[t2[1].componentName].stateValues.value, + ); + expect(t2math.equals(option[t2string])).eq(true); + + let u2 = + stateVariables[stateVariables["/u2"].replacements![0].componentName] + .activeChildren; + let u2string = u2[0]; + let u2math = me.fromAst( + stateVariables[u2[1].componentName].stateValues.value, + ); + expect(u2math.equals(option[u2string])).eq(true); + }); + + it("references to outside components, no new namespace", async () => { + let core = await createTestCore({ + doenetML: ` + x + y + z + + + + a + b + c + +

Selected options repeated

+ $q{name="q2"} + $r{name="r2"} + $s{name="s2"} + $t{name="t2"} + $u{name="u2"} + + `, + }); + + let option = { + "Option 1: ": me.fromText("3xa"), + "Option 2: ": me.fromText("4yb"), + "Option 3: ": me.fromText("5zc"), + }; + + let stateVariables = await returnAllStateVariables(core); + + let q2 = + stateVariables[stateVariables["/q2"].replacements![0].componentName] + .activeChildren; + let q2string = q2[0]; + let q2math = me.fromAst( + stateVariables[q2[1].componentName].stateValues.value, + ); + expect(q2math.equals(option[q2string])).eq(true); + + let r2 = + stateVariables[stateVariables["/r2"].replacements![0].componentName] + .activeChildren; + let r2string = r2[0]; + let r2math = me.fromAst( + stateVariables[r2[1].componentName].stateValues.value, + ); + expect(r2math.equals(option[r2string])).eq(true); + + let s2 = + stateVariables[stateVariables["/s2"].replacements![0].componentName] + .activeChildren; + let s2string = s2[0]; + let s2math = me.fromAst( + stateVariables[s2[1].componentName].stateValues.value, + ); + expect(s2math.equals(option[s2string])).eq(true); + + let t2 = + stateVariables[stateVariables["/t2"].replacements![0].componentName] + .activeChildren; + let t2string = t2[0]; + let t2math = me.fromAst( + stateVariables[t2[1].componentName].stateValues.value, + ); + expect(t2math.equals(option[t2string])).eq(true); + + let u2 = + stateVariables[stateVariables["/u2"].replacements![0].componentName] + .activeChildren; + let u2string = u2[0]; + let u2math = me.fromAst( + stateVariables[u2[1].componentName].stateValues.value, + ); + expect(u2math.equals(option[u2string])).eq(true); + }); + + it("internal references", async () => { + let core = await createTestCore({ + doenetML: ` + + +

Selected options repeated

+ $q{name="q2"} + $r{name="r2"} + $s{name="s2"} + $t{name="t2"} + $u{name="u2"} + +

Copy x from within selection options

+

$(q/x{name="qx"})

+

$(r/x{name="rx"})

+

$(s/x{name="sx"})

+

$(t/x{name="tx"})

+

$(u/x{name="ux"})

+ +

Copy select itself

+
$s1
+ + `, + }); + + let option = { + "Option 1: ": me.fromText("3x+a+x^2a^3"), + "Option 2: ": me.fromText("4y+b+y^2b^3"), + "Option 3: ": me.fromText("5z+c+z^2c^3"), + }; + + let xoption = { + "Option 1: ": "x", + "Option 2: ": "y", + "Option 3: ": "z", + }; + + let stateVariables = await returnAllStateVariables(core); + + let q2 = + stateVariables[stateVariables["/q2"].replacements![0].componentName] + .activeChildren; + let q2string = q2[0]; + let q2math = stateVariables[q2[1].componentName].stateValues.value; + expect(q2math.equals(option[q2string])).eq(true); + let qx = stateVariables["/qx"].stateValues.value.tree; + expect(qx).eq(xoption[q2string]); + let repeatqmath = + stateVariables[ + stateVariables[ + stateVariables["/repeat"].activeChildren[0].componentName + ].activeChildren[1].componentName + ].stateValues.value; + expect(repeatqmath.equals(option[q2string])).eq(true); + + let r2 = + stateVariables[stateVariables["/r2"].replacements![0].componentName] + .activeChildren; + let r2string = r2[0]; + let r2math = stateVariables[r2[1].componentName].stateValues.value; + expect(r2math.equals(option[r2string])).eq(true); + let rx = stateVariables["/rx"].stateValues.value.tree; + expect(rx).eq(xoption[r2string]); + let repeatrmath = + stateVariables[ + stateVariables[ + stateVariables["/repeat"].activeChildren[1].componentName + ].activeChildren[1].componentName + ].stateValues.value; + expect(repeatrmath.equals(option[r2string])).eq(true); + + let s2 = + stateVariables[stateVariables["/s2"].replacements![0].componentName] + .activeChildren; + let s2string = s2[0]; + let s2math = stateVariables[s2[1].componentName].stateValues.value; + expect(s2math.equals(option[s2string])).eq(true); + let sx = stateVariables["/sx"].stateValues.value.tree; + expect(sx).eq(xoption[s2string]); + let repeatsmath = + stateVariables[ + stateVariables[ + stateVariables["/repeat"].activeChildren[2].componentName + ].activeChildren[1].componentName + ].stateValues.value; + expect(repeatsmath.equals(option[s2string])).eq(true); + + let t2 = + stateVariables[stateVariables["/t2"].replacements![0].componentName] + .activeChildren; + let t2string = t2[0]; + let t2math = stateVariables[t2[1].componentName].stateValues.value; + expect(t2math.equals(option[t2string])).eq(true); + let tx = stateVariables["/tx"].stateValues.value.tree; + expect(tx).eq(xoption[t2string]); + let repeattmath = + stateVariables[ + stateVariables[ + stateVariables["/repeat"].activeChildren[3].componentName + ].activeChildren[1].componentName + ].stateValues.value; + expect(repeattmath.equals(option[t2string])).eq(true); + + let u2 = + stateVariables[stateVariables["/u2"].replacements![0].componentName] + .activeChildren; + let u2string = u2[0]; + let u2math = stateVariables[u2[1].componentName].stateValues.value; + expect(u2math.equals(option[u2string])).eq(true); + let ux = stateVariables["/ux"].stateValues.value.tree; + expect(ux).eq(xoption[u2string]); + let repeatumath = + stateVariables[ + stateVariables[ + stateVariables["/repeat"].activeChildren[4].componentName + ].activeChildren[1].componentName + ].stateValues.value; + expect(repeatumath.equals(option[u2string])).eq(true); + }); + + it("internal references with no new namespace", async () => { + let core = await createTestCore({ + doenetML: ` + + +

Selected options repeated

+ $q{name="q2"} + $r{name="r2"} + $s{name="s2"} + $t{name="t2"} + $u{name="u2"} + +

Copy select itself

+
$s1
+ + `, + }); + + let option = { + "Option 1: ": me.fromText("3x+a+x^2a^3"), + "Option 2: ": me.fromText("4y+b+y^2b^3"), + "Option 3: ": me.fromText("5z+c+z^2c^3"), + }; + + let xoption = { + "Option 1: ": "x", + "Option 2: ": "y", + "Option 3: ": "z", + }; + + let stateVariables = await returnAllStateVariables(core); + + let q2 = + stateVariables[stateVariables["/q2"].replacements![0].componentName] + .activeChildren; + let q2string = q2[0]; + let q2math = stateVariables[q2[1].componentName].stateValues.value; + expect(q2math.equals(option[q2string])).eq(true); + let repeatqmath = + stateVariables[ + stateVariables[ + stateVariables["/repeat"].activeChildren[0].componentName + ].activeChildren[1].componentName + ].stateValues.value; + expect(repeatqmath.equals(option[q2string])).eq(true); + + let r2 = + stateVariables[stateVariables["/r2"].replacements![0].componentName] + .activeChildren; + let r2string = r2[0]; + let r2math = stateVariables[r2[1].componentName].stateValues.value; + expect(r2math.equals(option[r2string])).eq(true); + let repeatrmath = + stateVariables[ + stateVariables[ + stateVariables["/repeat"].activeChildren[1].componentName + ].activeChildren[1].componentName + ].stateValues.value; + expect(repeatrmath.equals(option[r2string])).eq(true); + + let s2 = + stateVariables[stateVariables["/s2"].replacements![0].componentName] + .activeChildren; + let s2string = s2[0]; + let s2math = stateVariables[s2[1].componentName].stateValues.value; + expect(s2math.equals(option[s2string])).eq(true); + let repeatsmath = + stateVariables[ + stateVariables[ + stateVariables["/repeat"].activeChildren[2].componentName + ].activeChildren[1].componentName + ].stateValues.value; + expect(repeatsmath.equals(option[s2string])).eq(true); + + let t2 = + stateVariables[stateVariables["/t2"].replacements![0].componentName] + .activeChildren; + let t2string = t2[0]; + let t2math = stateVariables[t2[1].componentName].stateValues.value; + expect(t2math.equals(option[t2string])).eq(true); + let repeattmath = + stateVariables[ + stateVariables[ + stateVariables["/repeat"].activeChildren[3].componentName + ].activeChildren[1].componentName + ].stateValues.value; + expect(repeattmath.equals(option[t2string])).eq(true); + + let u2 = + stateVariables[stateVariables["/u2"].replacements![0].componentName] + .activeChildren; + let u2string = u2[0]; + let u2math = stateVariables[u2[1].componentName].stateValues.value; + expect(u2math.equals(option[u2string])).eq(true); + let repeatumath = + stateVariables[ + stateVariables[ + stateVariables["/repeat"].activeChildren[4].componentName + ].activeChildren[1].componentName + ].stateValues.value; + expect(repeatumath.equals(option[u2string])).eq(true); + }); + + it("variant names specified, select single", async () => { + let core = await createTestCore({ + doenetML: ` + + +

Selected variable: + +

+ +

Selected variable repeated: $x{name="x2"}

+

Selected variable repeated again: $s1{name="x3"}

+ `, + requestedVariantIndex: 2, + }); + + let stateVariables = await returnAllStateVariables(core); + + // let variantName = stateVariables['/x'].sharedParameters.variantName; + // let expectedx = variantName.substring(0, 1); + let expectedx = "b"; + + let x = stateVariables["/x"].stateValues.value.tree; + + expect(x).eq(expectedx); + + let xorig = + stateVariables[ + stateVariables[ + stateVariables["/s1"].replacements![0].componentName + ].replacements![0].componentName + ].stateValues.value.tree; + expect(xorig).eq(expectedx); + + let x2 = stateVariables["/x2"].stateValues.value.tree; + expect(x2).eq(expectedx); + + let x3 = + stateVariables[ + stateVariables[ + stateVariables["/x3"].replacements![0].componentName + ].replacements![0].componentName + ].stateValues.value.tree; + expect(x3).eq(expectedx); + }); + + it("variant names specified, select multiple", async () => { + let core = await createTestCore({ + doenetML: ` + + +

Selected variables: + +

+ +

Selected first variable: $x{name="x2"}

+

Selected second variable: $y{name="y2"}

+

Selected third variable: $z{name="z2"}

+

Selected variables repeated: $s1{name="s2"}

+ + `, + requestedVariantIndex: 3, + }); + + let stateVariables = await returnAllStateVariables(core); + + let variantMap = { + avocado: ["d", "a", "a"], + broccoli: ["e", "a", "b"], + carrot: ["d", "c", "b"], + dill: ["d", "e", "b"], + eggplant: ["c", "c", "e"], + }; + + // let variantName = stateVariables['/x'].sharedParameters.variantName; + let variantName = "carrot"; + let variantVars = variantMap[variantName]; + + let x = stateVariables["/x"].stateValues.value.tree; + + expect(variantVars.includes(x)).eq(true); + variantVars.splice(variantVars.indexOf(x), 1); + + let y = stateVariables["/y"].stateValues.value.tree; + expect(variantVars.includes(y)).eq(true); + variantVars.splice(variantVars.indexOf(y), 1); + + let z = stateVariables["/z"].stateValues.value.tree; + expect(z).eq(variantVars[0]); + + let xorig = + stateVariables[ + stateVariables[ + stateVariables["/s1"].replacements![0].componentName + ].replacements![0].componentName + ].stateValues.value.tree; + expect(xorig).eq(x); + let yorig = + stateVariables[ + stateVariables[ + stateVariables["/s1"].replacements![1].componentName + ].replacements![0].componentName + ].stateValues.value.tree; + expect(yorig).eq(y); + let zorig = + stateVariables[ + stateVariables[ + stateVariables["/s1"].replacements![2].componentName + ].replacements![0].componentName + ].stateValues.value.tree; + expect(zorig).eq(z); + + let x2 = stateVariables["/x2"].stateValues.value.tree; + expect(x2).eq(x); + let y2 = stateVariables["/y2"].stateValues.value.tree; + expect(y2).eq(y); + let z2 = stateVariables["/z2"].stateValues.value.tree; + expect(z2).eq(z); + + let x3 = + stateVariables[ + stateVariables[ + stateVariables["/s2"].replacements![0].componentName + ].replacements![0].componentName + ].stateValues.value.tree; + expect(x3).eq(x); + let y3 = + stateVariables[ + stateVariables[ + stateVariables["/s2"].replacements![1].componentName + ].replacements![0].componentName + ].stateValues.value.tree; + expect(y3).eq(y); + let z3 = + stateVariables[ + stateVariables[ + stateVariables["/s2"].replacements![2].componentName + ].replacements![0].componentName + ].stateValues.value.tree; + expect(z3).eq(z); + }); + + it("select math as sugared string", async () => { + const doenetML = ` + `; + + const vals = ["x^2", "x/y", "u", "a", "b-c", "s+t", "mn", "-1"].map( + (x) => me.fromText(x), + ); + + const valid_values = Array(5).fill(vals); + const componentNames = ["/m1", "/m2", "/m3", "/m4", "/m5"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 2, + is_math: true, + must_be_distinct: true, + }); + }); + + it("select math as sugared string, no type specified", async () => { + const doenetML = ` + `; + + const vals = ["x^2", "x/y", "u", "a", "b-c", "s+t", "mn", "-1"].map( + (x) => me.fromText(x), + ); + + const valid_values = Array(5).fill(vals); + const componentNames = ["/m1", "/m2", "/m3", "/m4", "/m5"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 2, + is_math: true, + must_be_distinct: true, + }); + }); + + it("select math as sugared strings and macros", async () => { + const doenetML = ` + + x + y + 7 + -3 + + `; + + const vals = ["7x^2", "(-3)x/y", "u-(-3)", "7", "x-c", "y"].map((x) => + me.fromText(x), + ); + + const valid_values = Array(6).fill(vals); + const componentNames = ["/m1", "/m2", "/m3", "/m4", "/m5", "/m6"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 2, + is_math: true, + must_be_distinct: true, + }); + }); + + it("select text as sugared string", async () => { + const doenetML = ` + `; + + const vals = [ + "Lorem", + "ipsum", + "dolor", + "sit", + "amet", + "consectetur", + "adipiscing", + "elit", + ]; + + const valid_values = Array(5).fill(vals); + const componentNames = ["/w1", "/w2", "/w3", "/w4", "/w5"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 2, + must_be_distinct: true, + }); + }); + + it("select text as sugared strings and macros", async () => { + const doenetML = ` + + amet + consectetur + dolor + + `; + + const vals = [ + "Lorem", + "ipsum dolor", + "sit", + "amet", + "consectetur adipiscing", + ]; + + const valid_values = Array(5).fill(vals); + const componentNames = ["/w1", "/w2", "/w3", "/w4", "/w5"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 2, + must_be_distinct: true, + }); + }); + + it("select number as sugared string", async () => { + const doenetML = ` + `; + + const vals = [2, 3, 5, 7, 11, 13, 17, 19]; + const valid_values = Array(10).fill(vals); + + const componentNames = [ + "/n1", + "/n2", + "/n3", + "/n4", + "/n5", + "/n6", + "/n7", + "/n8", + "/n9", + "/n10", + ]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 2, + }); + }); + + it("select number as sugared strings and macros", async () => { + const doenetML = ` + + 5 + -7 + 6+2 + + `; + + const vals = [2, -2, -5, 5, -8, 8]; + const valid_values = Array(6).fill(vals); + + const componentNames = ["/n1", "/n2", "/n3", "/n4", "/n5", "/n6"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 2, + must_be_distinct: true, + }); + }); + + it("select boolean as sugared string", async () => { + const doenetML = ` + `; + + const vals = [true, false]; + const valid_values = Array(10).fill(vals); + + const componentNames = [ + "/b1", + "/b2", + "/b3", + "/b4", + "/b5", + "/b6", + "/b7", + "/b8", + "/b9", + "/b10", + ]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 1, + }); + }); + + it("select boolean as sugared strings and macros", async () => { + const doenetML = ` + + true + false + + `; + + const vals = [true, false]; + const valid_values = Array(10).fill(vals); + + const componentNames = [ + "/b1", + "/b2", + "/b3", + "/b4", + "/b5", + "/b6", + "/b7", + "/b8", + "/b9", + "/b10", + ]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 1, + }); + }); + + it("select invalid type with sugared string, becomes math with warning", async () => { + const doenetML = ` + `; + + const vals = ["x^2", "x/y", "u", "a", "b-c", "s+t", "mn", "-1"].map( + (x) => me.fromText(x), + ); + + const valid_values = Array(5).fill(vals); + const componentNames = ["/m1", "/m2", "/m3", "/m4", "/m5"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 2, + is_math: true, + must_be_distinct: true, + }); + + let core = await createTestCore({ doenetML }); + + let errorWarnings = core.errorWarnings; + + expect(errorWarnings.errors.length).eq(0); + expect(errorWarnings.warnings.length).eq(1); + + expect(errorWarnings.warnings[0].message).contain( + "Invalid type for select: nothing", + ); + expect(errorWarnings.warnings[0].level).eq(1); + expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(2); + expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(5); + expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(4); + expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(13); + }); + + it("select weighted", async () => { + // TODO: this test seems to fail with num Y < 17 once in awhile + // even though it should fail less than 0.1% of the time + // Is there a flaw? + + let core = await createTestCore({ + doenetML: ` + + + + + `, + }); + + let numX = 0, + numY = 0, + numZ = 0; + + let stateVariables = await returnAllStateVariables(core); + for (let ind = 0; ind < 200; ind++) { + let theText = + stateVariables[ + stateVariables[ + stateVariables[ + stateVariables[ + stateVariables["/_map1"].replacements![ind] + .componentName + ].replacements![1].componentName + ].replacements![0].componentName + ].replacements![0].componentName + ]; + let x = theText.stateValues.value; + if (x === "z") { + numZ++; + } else if (x === "y") { + numY++; + } else { + numX++; + } + } + + expect(numX).greaterThan(0); + expect(numX).lessThan(15); + expect(numY).greaterThan(17); + expect(numY).lessThan(50); + expect(numZ).greaterThan(140); + }); + + it("select weighted with replacement", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + requestedVariantIndex: 0, + }); + + let stateVariables = await returnAllStateVariables(core); + let numX = 0, + numY = 0, + numZ = 0; + let selectReplacements = stateVariables["/_select1"].replacements!; + for (let ind = 0; ind < 200; ind++) { + let x = + stateVariables[ + stateVariables[selectReplacements[ind].componentName] + .replacements![0].componentName + ].stateValues.value; + if (x === "x") { + numX++; + } else if (x === "y") { + numY++; + } else { + numZ++; + } + } + expect(numX).greaterThan(0); + expect(numX).lessThan(15); + expect(numY).greaterThan(20); + expect(numY).lessThan(50); + expect(numZ).greaterThan(150); + }); + + it("select weighted without replacement", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + `, + }); + + let numX = 0, + numY = 0, + numZ = 0, + numUVW = 0; + + let stateVariables = await returnAllStateVariables(core); + + for (let ind = 0; ind < 200; ind++) { + let theSelect = + stateVariables[ + stateVariables[ + stateVariables["/_map1"].replacements![ind] + .componentName + ].replacements![1].componentName + ]; + let theText1 = + stateVariables[ + stateVariables[theSelect.replacements![0].componentName] + .replacements![0].componentName + ]; + let x = theText1.stateValues.value; + + if (x === "z") { + numZ++; + } else if (x === "y") { + numY++; + } else if (x === "x") { + numX++; + } else { + numUVW++; + } + let theText2 = + stateVariables[ + stateVariables[theSelect.replacements![1].componentName] + .replacements![0].componentName + ]; + let y = theText2.stateValues.value; + if (y === "z") { + numZ++; + } else if (y === "y") { + numY++; + } else if (y === "x") { + numX++; + } else { + numUVW++; + } + } + + expect(numUVW).greaterThan(0); + expect(numUVW).lessThan(20); + expect(numX).greaterThan(150); + expect(numY).greaterThan(10); + expect(numY).lessThan(50); + expect(numZ).greaterThan(170); + }); + + it("references to internal assignnames", async () => { + let core = await createTestCore({ + doenetML: ` + a e i o u$q{name="q2"}$r{name="r2"}

+ + + + + +

Selected options repeated

+ $q{name="q2"} + $r{name="r2"} + $s{name="s2"} + $t{name="t2"} + $u{name="u2"} + $v{name="v2"} + $w{name="w2"} + +

Copy q and r and their copies from within selected options

+

$(q/q{name="qq"})$(q/r{name="qr"})$(q/q2{name="qq2"})$(q/r2{name="qr2"})

+

$(r/q{name="rq"})$(r/r{name="rr"})$(r/q2{name="rq2"})$(r/r2{name="rr2"})

+

$(s/q{name="sq"})$(s/r{name="sr"})$(s/q2{name="sq2"})$(s/r2{name="sr2"})

+

$(t/q{name="tq"})$(t/r{name="tr"})$(t/q2{name="tq2"})$(t/r2{name="tr2"})

+

$(u/q{name="uq"})$(u/r{name="ur"})$(u/q2{name="uq2"})$(u/r2{name="ur2"})

+

$(v/q{name="vq"})$(v/r{name="vr"})$(v/q2{name="vq2"})$(v/r2{name="vr2"})

+

$(w/q{name="wq"})$(w/r{name="wr"})$(w/q2{name="wq2"})$(w/r2{name="wr2"})

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + let qs = stateVariables["/q"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let rs = stateVariables["/r"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let ss = stateVariables["/s"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let ts = stateVariables["/t"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let us = stateVariables["/u"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let vs = stateVariables["/v"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let ws = stateVariables["/w"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + + let q2s = stateVariables["/q2"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let r2s = stateVariables["/r2"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let s2s = stateVariables["/s2"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let t2s = stateVariables["/t2"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let u2s = stateVariables["/u2"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let v2s = stateVariables["/v2"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let w2s = stateVariables["/w2"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + + const getTree = (x) => x.tree ?? x; + + expect(q2s.map(getTree)).eqls(qs.map(getTree)); + expect(r2s.map(getTree)).eqls(rs.map(getTree)); + expect(s2s.map(getTree)).eqls(ss.map(getTree)); + expect(t2s.map(getTree)).eqls(ts.map(getTree)); + expect(u2s.map(getTree)).eqls(us.map(getTree)); + expect(v2s.map(getTree)).eqls(vs.map(getTree)); + expect(w2s.map(getTree)).eqls(ws.map(getTree)); + + let q3s = [ + stateVariables["/qq"].stateValues.value, + stateVariables["/qr"].stateValues.value, + stateVariables["/qq2"].stateValues.value, + stateVariables["/qr2"].stateValues.value, + ]; + let r3s = [ + stateVariables["/rq"].stateValues.value, + stateVariables["/rr"].stateValues.value, + stateVariables["/rq2"].stateValues.value, + stateVariables["/rr2"].stateValues.value, + ]; + let s3s = [ + stateVariables["/sq"].stateValues.value, + stateVariables["/sr"].stateValues.value, + stateVariables["/sq2"].stateValues.value, + stateVariables["/sr2"].stateValues.value, + ]; + let t3s = [ + stateVariables["/tq"].stateValues.value, + stateVariables["/tr"].stateValues.value, + stateVariables["/tq2"].stateValues.value, + stateVariables["/tr2"].stateValues.value, + ]; + let u3s = [ + stateVariables["/uq"].stateValues.value, + stateVariables["/ur"].stateValues.value, + stateVariables["/uq2"].stateValues.value, + stateVariables["/ur2"].stateValues.value, + ]; + let v3s = [ + stateVariables["/vq"].stateValues.value, + stateVariables["/vr"].stateValues.value, + stateVariables["/vq2"].stateValues.value, + stateVariables["/vr2"].stateValues.value, + ]; + let w3s = [ + stateVariables["/wq"].stateValues.value, + stateVariables["/wr"].stateValues.value, + stateVariables["/wq2"].stateValues.value, + stateVariables["/wr2"].stateValues.value, + ]; + + expect(q3s.map(getTree)).eqls(qs.map(getTree)); + expect(r3s.map(getTree)).eqls(rs.map(getTree)); + expect(s3s.map(getTree)).eqls(ss.map(getTree)); + expect(t3s.map(getTree)).eqls(ts.map(getTree)); + expect(u3s.map(getTree)).eqls(us.map(getTree)); + expect(v3s.map(getTree)).eqls(vs.map(getTree)); + expect(w3s.map(getTree)).eqls(ws.map(getTree)); + }); + + it("references to internal assignnames, newnamespaces", async () => { + let core = await createTestCore({ + doenetML: ` + a e i o u$(s/q{name="q2"})$(s/r{name="r2"})

+ + + + +

Selected options repeated

+ $q{name="q2"} + $r{name="r2"} + $s{name="s2"} + $t{name="t2"} + $u{name="u2"} + $v{name="v2"} + $w{name="w2"} + +

Selected options repeated, no p

+

$(q/s{name="q3"})

+

$(r/s{name="r3"})

+

$(s/s{name="s3"})

+

$(t/s{name="t3"})

+

$(u/s{name="u3"})

+

$(v/s{name="v3"})

+

$(w/s{name="w3"})

+ +

Copy q and r from within selected options

+

$(q/s/q{name="qq"})$(q/s/r{name="qr"})$(q/q2{name="qq2"})$(q/r2{name="qr2"})

+

$(r/s/q{name="rq"})$(r/s/r{name="rr"})$(r/q2{name="rq2"})$(r/r2{name="rr2"})

+

$(s/s/q{name="sq"})$(s/s/r{name="sr"})$(s/q2{name="sq2"})$(s/r2{name="sr2"})

+

$(t/s/q{name="tq"})$(t/s/r{name="tr"})$(t/q2{name="tq2"})$(t/r2{name="tr2"})

+

$(u/s/q{name="uq"})$(u/s/r{name="ur"})$(u/q2{name="uq2"})$(u/r2{name="ur2"})

+

$(v/s/q{name="vq"})$(v/s/r{name="vr"})$(v/q2{name="vq2"})$(v/r2{name="vr2"})

+

$(w/s/q{name="wq"})$(w/s/r{name="wr"})$(w/q2{name="wq2"})$(w/r2{name="wr2"})

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + let qs = stateVariables["/q"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let rs = stateVariables["/r"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let ss = stateVariables["/s"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let ts = stateVariables["/t"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let us = stateVariables["/u"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let vs = stateVariables["/v"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let ws = stateVariables["/w"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + + let q2s = stateVariables["/q2"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let r2s = stateVariables["/r2"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let s2s = stateVariables["/s2"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let t2s = stateVariables["/t2"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let u2s = stateVariables["/u2"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let v2s = stateVariables["/v2"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let w2s = stateVariables["/w2"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + + const getTree = (x) => x.tree ?? x; + + expect(q2s.map(getTree)).eqls(qs.map(getTree)); + expect(r2s.map(getTree)).eqls(rs.map(getTree)); + expect(s2s.map(getTree)).eqls(ss.map(getTree)); + expect(t2s.map(getTree)).eqls(ts.map(getTree)); + expect(u2s.map(getTree)).eqls(us.map(getTree)); + expect(v2s.map(getTree)).eqls(vs.map(getTree)); + expect(w2s.map(getTree)).eqls(ws.map(getTree)); + + let q3s = stateVariables["/q3"] + .replacements!.map((x) => stateVariables[x.componentName]) + .map((x) => + x.replacements + ? stateVariables[x.replacements[0].componentName] + .stateValues.value + : x.stateValues.value, + ); + let r3s = stateVariables["/r3"] + .replacements!.map((x) => stateVariables[x.componentName]) + .map((x) => + x.replacements + ? stateVariables[x.replacements[0].componentName] + .stateValues.value + : x.stateValues.value, + ); + let s3s = stateVariables["/s3"] + .replacements!.map((x) => stateVariables[x.componentName]) + .map((x) => + x.replacements + ? stateVariables[x.replacements[0].componentName] + .stateValues.value + : x.stateValues.value, + ); + let t3s = stateVariables["/t3"] + .replacements!.map((x) => stateVariables[x.componentName]) + .map((x) => + x.replacements + ? stateVariables[x.replacements[0].componentName] + .stateValues.value + : x.stateValues.value, + ); + let u3s = stateVariables["/u3"] + .replacements!.map((x) => stateVariables[x.componentName]) + .map((x) => + x.replacements + ? stateVariables[x.replacements[0].componentName] + .stateValues.value + : x.stateValues.value, + ); + let v3s = stateVariables["/v3"] + .replacements!.map((x) => stateVariables[x.componentName]) + .map((x) => + x.replacements + ? stateVariables[x.replacements[0].componentName] + .stateValues.value + : x.stateValues.value, + ); + let w3s = stateVariables["/w3"] + .replacements!.map((x) => stateVariables[x.componentName]) + .map((x) => + x.replacements + ? stateVariables[x.replacements[0].componentName] + .stateValues.value + : x.stateValues.value, + ); + + expect(q3s.map(getTree)).eqls(qs.slice(0, 2).map(getTree)); + expect(r3s.map(getTree)).eqls(rs.slice(0, 2).map(getTree)); + expect(s3s.map(getTree)).eqls(ss.slice(0, 2).map(getTree)); + expect(t3s.map(getTree)).eqls(ts.slice(0, 2).map(getTree)); + expect(u3s.map(getTree)).eqls(us.slice(0, 2).map(getTree)); + expect(v3s.map(getTree)).eqls(vs.slice(0, 2).map(getTree)); + expect(w3s.map(getTree)).eqls(ws.slice(0, 2).map(getTree)); + + let q4s = [ + stateVariables["/qq"].stateValues.value, + stateVariables["/qr"].stateValues.value, + stateVariables["/qq2"].stateValues.value, + stateVariables["/qr2"].stateValues.value, + ]; + let r4s = [ + stateVariables["/rq"].stateValues.value, + stateVariables["/rr"].stateValues.value, + stateVariables["/rq2"].stateValues.value, + stateVariables["/rr2"].stateValues.value, + ]; + let s4s = [ + stateVariables["/sq"].stateValues.value, + stateVariables["/sr"].stateValues.value, + stateVariables["/sq2"].stateValues.value, + stateVariables["/sr2"].stateValues.value, + ]; + let t4s = [ + stateVariables["/tq"].stateValues.value, + stateVariables["/tr"].stateValues.value, + stateVariables["/tq2"].stateValues.value, + stateVariables["/tr2"].stateValues.value, + ]; + let u4s = [ + stateVariables["/uq"].stateValues.value, + stateVariables["/ur"].stateValues.value, + stateVariables["/uq2"].stateValues.value, + stateVariables["/ur2"].stateValues.value, + ]; + let v4s = [ + stateVariables["/vq"].stateValues.value, + stateVariables["/vr"].stateValues.value, + stateVariables["/vq2"].stateValues.value, + stateVariables["/vr2"].stateValues.value, + ]; + let w4s = [ + stateVariables["/wq"].stateValues.value, + stateVariables["/wr"].stateValues.value, + stateVariables["/wq2"].stateValues.value, + stateVariables["/wr2"].stateValues.value, + ]; + + expect(q4s.map(getTree)).eqls(qs.map(getTree)); + expect(r4s.map(getTree)).eqls(rs.map(getTree)); + expect(s4s.map(getTree)).eqls(ss.map(getTree)); + expect(t4s.map(getTree)).eqls(ts.map(getTree)); + expect(u4s.map(getTree)).eqls(us.map(getTree)); + expect(v4s.map(getTree)).eqls(vs.map(getTree)); + expect(w4s.map(getTree)).eqls(ws.map(getTree)); + }); + + it("references to select of selects", async () => { + let core = await createTestCore({ + doenetML: ` + a e i o u + + + +

Selected options repeated

+

$q{name="q2"}

+

$r{name="r2"}

+

$s{name="s2"}

+

$t{name="t2"}

+

$u{name="u2"}

+ +

Copy x/q and x/r

+

$(q/q{name="qq"})$(q/r{name="qr"})

+

$(r/q{name="rq"})$(r/r{name="rr"})

+

$(s/q{name="sq"})$(s/r{name="sr"})

+

$(t/q{name="tq"})$(t/r{name="tr"})

+

$(u/q{name="uq"})$(u/r{name="ur"})

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + let qs = stateVariables["/q"] + .replacements!.map((x) => stateVariables[x.componentName]) + .map((x) => + x.replacements + ? stateVariables[x.replacements[0].componentName] + .stateValues.value + : x.stateValues.value, + ); + let rs = stateVariables["/r"] + .replacements!.map((x) => stateVariables[x.componentName]) + .map((x) => + x.replacements + ? stateVariables[x.replacements[0].componentName] + .stateValues.value + : x.stateValues.value, + ); + let ss = stateVariables["/s"] + .replacements!.map((x) => stateVariables[x.componentName]) + .map((x) => + x.replacements + ? stateVariables[x.replacements[0].componentName] + .stateValues.value + : x.stateValues.value, + ); + let ts = stateVariables["/t"] + .replacements!.map((x) => stateVariables[x.componentName]) + .map((x) => + x.replacements + ? stateVariables[x.replacements[0].componentName] + .stateValues.value + : x.stateValues.value, + ); + let us = stateVariables["/u"] + .replacements!.map((x) => stateVariables[x.componentName]) + .map((x) => + x.replacements + ? stateVariables[x.replacements[0].componentName] + .stateValues.value + : x.stateValues.value, + ); + + let q2s = stateVariables["/q2"] + .replacements!.map((x) => stateVariables[x.componentName]) + .map((x) => + x.replacements + ? stateVariables[x.replacements[0].componentName] + .stateValues.value + : x.stateValues.value, + ); + let r2s = stateVariables["/r2"] + .replacements!.map((x) => stateVariables[x.componentName]) + .map((x) => + x.replacements + ? stateVariables[x.replacements[0].componentName] + .stateValues.value + : x.stateValues.value, + ); + let s2s = stateVariables["/s2"] + .replacements!.map((x) => stateVariables[x.componentName]) + .map((x) => + x.replacements + ? stateVariables[x.replacements[0].componentName] + .stateValues.value + : x.stateValues.value, + ); + let t2s = stateVariables["/t2"] + .replacements!.map((x) => stateVariables[x.componentName]) + .map((x) => + x.replacements + ? stateVariables[x.replacements[0].componentName] + .stateValues.value + : x.stateValues.value, + ); + let u2s = stateVariables["/u2"] + .replacements!.map((x) => stateVariables[x.componentName]) + .map((x) => + x.replacements + ? stateVariables[x.replacements[0].componentName] + .stateValues.value + : x.stateValues.value, + ); + + const getTree = (x) => x.tree ?? x; + + expect(q2s.map(getTree)).eqls(qs.map(getTree)); + expect(r2s.map(getTree)).eqls(rs.map(getTree)); + expect(s2s.map(getTree)).eqls(ss.map(getTree)); + expect(t2s.map(getTree)).eqls(ts.map(getTree)); + expect(u2s.map(getTree)).eqls(us.map(getTree)); + + let q3s = [ + stateVariables["/qq"].stateValues.value, + stateVariables["/qr"].stateValues.value, + ]; + let r3s = [ + stateVariables["/rq"].stateValues.value, + stateVariables["/rr"].stateValues.value, + ]; + let s3s = [ + stateVariables["/sq"].stateValues.value, + stateVariables["/sr"].stateValues.value, + ]; + let t3s = [ + stateVariables["/tq"].stateValues.value, + stateVariables["/tr"].stateValues.value, + ]; + let u3s = [ + stateVariables["/uq"].stateValues.value, + stateVariables["/ur"].stateValues.value, + ]; + + expect(q3s.map(getTree)).eqls(qs.map(getTree)); + expect(r3s.map(getTree)).eqls(rs.map(getTree)); + expect(s3s.map(getTree)).eqls(ss.map(getTree)); + expect(t3s.map(getTree)).eqls(ts.map(getTree)); + expect(u3s.map(getTree)).eqls(us.map(getTree)); + }); + + it("references to select of selects of selects", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + + + +

Selected options repeated

+

$q{name="q2"}

+

$r{name="r2"}

+

$s{name="s2"}

+ +

Copy x/q, x/r, x/s

+

$(q/q{name="qq"})$(q/r{name="qr"})$(q/s{name="qs"})

+

$(r/q{name="rq"})$(r/r{name="rr"})$(r/s{name="rs"})

+

$(s/q{name="sq"})$(s/r{name="sr"})$(s/s{name="ss"})

+ +

Copy x/x/q, x/x/r

+

$(q/q/q{name="qqq"})$(q/q/r{name="qqr"})$(q/r/q{name="qrq"})$(q/r/r{name="qrr"})$(q/s/q{name="qsq"})$(q/s/r{name="qsr"})

+

$(r/q/q{name="rqq"})$(r/q/r{name="rqr"})$(r/r/q{name="rrq"})$(r/r/r{name="rrr"})$(r/s/q{name="rsq"})$(r/s/r{name="rsr"})

+

$(s/q/q{name="sqq"})$(s/q/r{name="sqr"})$(s/r/q{name="srq"})$(s/r/r{name="srr"})$(s/s/q{name="ssq"})$(s/s/r{name="ssr"})

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + let qs = [ + "/q/q/q", + "/q/q/r", + "/q/r/q", + "/q/r/r", + "/q/s/q", + "/q/s/r", + ].map((x) => + stateVariables[x].replacements + ? stateVariables[ + stateVariables[x].replacements[0].componentName + ].stateValues.value + : stateVariables[x].stateValues.value, + ); + let rs = [ + "/r/q/q", + "/r/q/r", + "/r/r/q", + "/r/r/r", + "/r/s/q", + "/r/s/r", + ].map((x) => + stateVariables[x].replacements + ? stateVariables[ + stateVariables[x].replacements[0].componentName + ].stateValues.value + : stateVariables[x].stateValues.value, + ); + let ss = [ + "/s/q/q", + "/s/q/r", + "/s/r/q", + "/s/r/r", + "/s/s/q", + "/s/s/r", + ].map((x) => + stateVariables[x].replacements + ? stateVariables[ + stateVariables[x].replacements[0].componentName + ].stateValues.value + : stateVariables[x].stateValues.value, + ); + + expect(stateVariables["/pq2"].stateValues.text.replace(/, /g, "")).eq( + qs.join(""), + ); + expect(stateVariables["/pr2"].stateValues.text.replace(/, /g, "")).eq( + rs.join(""), + ); + expect(stateVariables["/ps2"].stateValues.text.replace(/, /g, "")).eq( + ss.join(""), + ); + + expect(stateVariables["/pq3"].stateValues.text.replace(/, /g, "")).eq( + qs.join(""), + ); + expect(stateVariables["/pr3"].stateValues.text.replace(/, /g, "")).eq( + rs.join(""), + ); + expect(stateVariables["/ps3"].stateValues.text.replace(/, /g, "")).eq( + ss.join(""), + ); + + expect(stateVariables["/pq4"].stateValues.text.replace(/, /g, "")).eq( + qs.join(""), + ); + expect(stateVariables["/pr4"].stateValues.text.replace(/, /g, "")).eq( + rs.join(""), + ); + expect(stateVariables["/ps4"].stateValues.text.replace(/, /g, "")).eq( + ss.join(""), + ); + }); + + it("references to select of selects of selects, newnamespaces", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + + + +

Selected options repeated

+

$(a/q{name="q2"})

+

$(a/r{name="r2"})

+

$(a/s{name="s2"})

+ +

Copy x/q, x/r, x/s

+

$(a/q/q{name="qq"})$(a/q/r{name="qr"})$(a/q/s{name="qs"})

+

$(a/r/q{name="rq"})$(a/r/r{name="rr"})$(a/r/s{name="rs"})

+

$(a/s/q{name="sq"})$(a/s/r{name="sr"})$(a/s/s{name="ss"})

+ +

Copy x/x/q, x/x/r

+

$(a/q/q/q{name="qqq"})$(a/q/q/r{name="qqr"})$(a/q/r/q{name="qrq"})$(a/q/r/r{name="qrr"})$(a/q/s/q{name="qsq"})$(a/q/s/r{name="qsr"})

+

$(a/r/q/q{name="rqq"})$(a/r/q/r{name="rqr"})$(a/r/r/q{name="rrq"})$(a/r/r/r{name="rrr"})$(a/r/s/q{name="rsq"})$(a/r/s/r{name="rsr"})

+

$(a/s/q/q{name="sqq"})$(a/s/q/r{name="sqr"})$(a/s/r/q{name="srq"})$(a/s/r/r{name="srr"})$(a/s/s/q{name="ssq"})$(a/s/s/r{name="ssr"})

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + let qs = [ + "/a/q/q/q", + "/a/q/q/r", + "/a/q/r/q", + "/a/q/r/r", + "/a/q/s/q", + "/a/q/s/r", + ].map((x) => + stateVariables[x].replacements + ? stateVariables[ + stateVariables[x].replacements[0].componentName + ].stateValues.value + : stateVariables[x].stateValues.value, + ); + let rs = [ + "/a/r/q/q", + "/a/r/q/r", + "/a/r/r/q", + "/a/r/r/r", + "/a/r/s/q", + "/a/r/s/r", + ].map((x) => + stateVariables[x].replacements + ? stateVariables[ + stateVariables[x].replacements[0].componentName + ].stateValues.value + : stateVariables[x].stateValues.value, + ); + let ss = [ + "/a/s/q/q", + "/a/s/q/r", + "/a/s/r/q", + "/a/s/r/r", + "/a/s/s/q", + "/a/s/s/r", + ].map((x) => + stateVariables[x].replacements + ? stateVariables[ + stateVariables[x].replacements[0].componentName + ].stateValues.value + : stateVariables[x].stateValues.value, + ); + + expect(stateVariables["/pq2"].stateValues.text.replace(/, /g, "")).eq( + qs.join(""), + ); + expect(stateVariables["/pr2"].stateValues.text.replace(/, /g, "")).eq( + rs.join(""), + ); + expect(stateVariables["/ps2"].stateValues.text.replace(/, /g, "")).eq( + ss.join(""), + ); + + expect(stateVariables["/pq3"].stateValues.text.replace(/, /g, "")).eq( + qs.join(""), + ); + expect(stateVariables["/pr3"].stateValues.text.replace(/, /g, "")).eq( + rs.join(""), + ); + expect(stateVariables["/ps3"].stateValues.text.replace(/, /g, "")).eq( + ss.join(""), + ); + + expect(stateVariables["/pq4"].stateValues.text.replace(/, /g, "")).eq( + qs.join(""), + ); + expect(stateVariables["/pr4"].stateValues.text.replace(/, /g, "")).eq( + rs.join(""), + ); + expect(stateVariables["/ps4"].stateValues.text.replace(/, /g, "")).eq( + ss.join(""), + ); + }); + + it("references to named grandchildren's children", async () => { + let core = await createTestCore({ + doenetML: ` + + +

Copy grandchidren

+

$a{name="a2"}

+

$b{name="b2"}

+

$c{name="c2"}

+

$d{name="d2"}

+ +

Copy named children of grandchild

+

$(a/w{name="w2"})

+

$(b/v{name="v2"})

+ + `, + }); + + let options = [ + { + a: "x y", + b: "3 z", + c: "x", + d: "z", + v: "z", + w: "x", + }, + { + a: "u v", + b: "3 t", + c: "u", + d: "t", + v: "t", + w: "u", + }, + ]; + + let stateVariables = await returnAllStateVariables(core); + + let chosenChildren = stateVariables[ + stateVariables["/_select1"].replacements![0].componentName + ] + .replacements!.filter((x) => typeof x !== "string") + .map((x) => stateVariables[x.componentName]) + .map((v, i) => + i < 2 ? v : stateVariables[v.replacements![0].componentName], + ); + let option = + options[ + stateVariables["/_select1"].stateValues.selectedIndices[0] - 1 + ]; + + expect(me.fromAst(chosenChildren[0].stateValues.value).toString()).eq( + option.a, + ); + expect(me.fromAst(chosenChildren[1].stateValues.value).toString()).eq( + option.b, + ); + expect(me.fromAst(chosenChildren[2].stateValues.value).toString()).eq( + option.c, + ); + expect(me.fromAst(chosenChildren[3].stateValues.value).toString()).eq( + option.d, + ); + + let a2 = me.fromAst(stateVariables["/a2"].stateValues.value).toString(); + let b2 = me.fromAst(stateVariables["/b2"].stateValues.value).toString(); + let c2 = me.fromAst(stateVariables["/c2"].stateValues.value).toString(); + let d2 = me.fromAst(stateVariables["/d2"].stateValues.value).toString(); + let v2 = me.fromAst(stateVariables["/v2"].stateValues.value).toString(); + let w2 = me.fromAst(stateVariables["/w2"].stateValues.value).toString(); + + expect(a2).eq(option.a); + expect(b2).eq(option.b); + expect(c2).eq(option.c); + expect(d2).eq(option.d); + expect(v2).eq(option.v); + expect(w2).eq(option.w); + }); + + it("select of a map of a select, with references", async () => { + let core = await createTestCore({ + doenetML: ` +

+ +

+ +

Copy whole select again

+

$_select1{name="s2"}

+ +

Copy individual selections

+

+ $j{name="j2"} + $k{name="k2"} + $l{name="l2"} +

+ +

Copy individual pieces

+

+ $(j/a/p{name="p1"})$(j/a/q{name="p2"})$(j/a/r{name="p3"})$(j/a/s{name="p4"})$(j/b/p{name="p5"})$(j/b/q{name="p6"})$(j/b/r{name="p7"})$(j/b/s{name="p8"}) + $(k/a/p{name="p9"})$(k/a/q{name="p10"})$(k/a/r{name="p11"})$(k/a/s{name="p12"})$(k/b/p{name="p13"})$(k/b/q{name="p14"})$(k/b/r{name="p15"})$(k/b/s{name="p16"}) + $(l/a/p{name="p17"})$(l/a/q{name="p18"})$(l/a/r{name="p19"})$(l/a/s{name="p20"})$(l/b/p{name="p21"})$(l/b/q{name="p22"})$(l/b/r{name="p23"})$(l/b/s{name="p24"}) +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let theList1 = stateVariables["/list1"].activeChildren.map((x) => + me + .fromAst(stateVariables[x.componentName].stateValues.value) + .toString(), + ); + let theList2 = stateVariables["/list2"].activeChildren.map((x) => + me + .fromAst(stateVariables[x.componentName].stateValues.value) + .toString(), + ); + let theList3 = stateVariables["/list3"].activeChildren.map((x) => + me + .fromAst(stateVariables[x.componentName].stateValues.value) + .toString(), + ); + + expect(theList2).eqls(theList1); + expect(theList3).eqls(theList1); + + let theList4 = [...Array(24).keys()].map((i) => + me + .fromAst(stateVariables["/p" + (i + 1)].stateValues.value) + .toString(), + ); + + expect(theList4).eqls(theList1); + }); + + it("select of a map of a select, new namespaces", async () => { + let core = await createTestCore({ + doenetML: ` +

+ +

+ +

Copy whole select again

+

$s{name="s2"}

+ +

Copy individual selections

+

+ $(s/j{name="j2"}) + $(s/k{name="k2"}) + $(s/l{name="l2"}) +

+ +

Copy individual pieces

+

+ $(s/j/a/v/p{name="p1"})$(s/j/a/v/q{name="p2"})$(s/j/a/v/r{name="p3"})$(s/j/a/v/s{name="p4"})$(s/j/b/v/p{name="p5"})$(s/j/b/v/q{name="p6"})$(s/j/b/v/r{name="p7"})$(s/j/b/v/s{name="p8"}) + $(s/k/a/v/p{name="p9"})$(s/k/a/v/q{name="p10"})$(s/k/a/v/r{name="p11"})$(s/k/a/v/s{name="p12"})$(s/k/b/v/p{name="p13"})$(s/k/b/v/q{name="p14"})$(s/k/b/v/r{name="p15"})$(s/k/b/v/s{name="p16"}) + $(s/l/a/v/p{name="p17"})$(s/l/a/v/q{name="p18"})$(s/l/a/v/r{name="p19"})$(s/l/a/v/s{name="p20"})$(s/l/b/v/p{name="p21"})$(s/l/b/v/q{name="p22"})$(s/l/b/v/r{name="p23"})$(s/l/b/v/s{name="p24"}) +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let theList1 = stateVariables["/list1"].activeChildren.map((x) => + me + .fromAst(stateVariables[x.componentName].stateValues.value) + .toString(), + ); + let theList2 = stateVariables["/list2"].activeChildren.map((x) => + me + .fromAst(stateVariables[x.componentName].stateValues.value) + .toString(), + ); + let theList3 = stateVariables["/list3"].activeChildren.map((x) => + me + .fromAst(stateVariables[x.componentName].stateValues.value) + .toString(), + ); + + expect(theList2).eqls(theList1); + expect(theList3).eqls(theList1); + + let theList4 = [...Array(24).keys()].map((i) => + me + .fromAst(stateVariables["/p" + (i + 1)].stateValues.value) + .toString(), + ); + + expect(theList4).eqls(theList1); + }); + + // Note: this test encodes undesired behavior (see issue #246) + // When this issue is resolved, change this test to make sure the references + // are hidden when the select is hidden + it("select with hide will hide replacements but not copies", async () => { + let core = await createTestCore({ + doenetML: ` +

Selects and hide

+

,

+

$c, $d

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let c = await stateVariables["/c"].stateValues.value; + let d = await stateVariables["/d"].stateValues.value; + expect(["a", "b", "c", "d", "e"].includes(c)).eq(true); + expect(["a", "b", "c", "d", "e"].includes(d)).eq(true); + + expect(stateVariables["/p1"].stateValues.text).eq(`${c}, `); + expect(stateVariables["/p2"].stateValues.text).eq(`${c}, ${d}`); + }); + + // Note: this test encodes undesired behavior (see issue #246) + // When this issue is resolved, change this test to make sure the references + // are hidden when the select is hidden + it("select with hide will hide named grandchildren replacements but not copies", async () => { + let core = await createTestCore({ + doenetML: ` +

Selects and hide

+

+

$a, , $c, , $e

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let a = stateVariables["/a"].stateValues.value; + let b = stateVariables["/b"].stateValues.value; + let c = stateVariables["/c"].stateValues.value; + let d = stateVariables["/d"].stateValues.value; + let e = stateVariables["/e"].stateValues.value; + expect(["a", "d"].includes(a)).eq(true); + expect(["b", "e"].includes(b)).eq(true); + expect(["c", "f"].includes(c)).eq(true); + expect(["a", "c", "e"].includes(d)).eq(true); + expect(["b", "d", "f"].includes(e)).eq(true); + + expect(stateVariables["/p1"].stateValues.text).eq(`${a}, ${b}, ${c}`); + expect(stateVariables["/p2"].stateValues.text).eq( + `${a}, , ${c}, ${d}, ${e}`, + ); + }); + + // Note: this test encodes undesired behavior (see issue #246) + // When this issue is resolved, change this test to make sure the references + // are hidden when the select is hidden + it("select with hide will hide named grandchildren replacements but not copies", async () => { + let core = await createTestCore({ + doenetML: ` +

Selects and hide

+

+

$a, , $c, , $e

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let a = stateVariables["/a"].stateValues.value; + let b = stateVariables["/b"].stateValues.value; + let c = stateVariables["/c"].stateValues.value; + let d = stateVariables["/d"].stateValues.value; + let e = stateVariables["/e"].stateValues.value; + expect(["a", "d"].includes(a)).eq(true); + expect(["b", "e"].includes(b)).eq(true); + expect(["c", "f"].includes(c)).eq(true); + expect(["a", "c", "e"].includes(d)).eq(true); + expect(["b", "d", "f"].includes(e)).eq(true); + + expect(stateVariables["/p1"].stateValues.text).eq(`${a}, ${b}, ${c}`); + expect(stateVariables["/p2"].stateValues.text).eq( + `${a}, , ${c}, ${d}, ${e}`, + ); + }); + + // Note: this test encodes undesired behavior (see issue #246) + // When this issue is resolved, change this test to make sure the references + // are hidden when the select is hidden + it("selects hide dynamically", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + +

,

+

$c, $d

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let c = await stateVariables["/c"].stateValues.value; + let d = await stateVariables["/d"].stateValues.value; + expect(["a", "b", "c", "d", "e"].includes(c)).eq(true); + expect(["a", "b", "c", "d", "e"].includes(d)).eq(true); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq(`${c}, `); + expect(stateVariables["/p2"].stateValues.text).eq(`${c}, ${d}`); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/h1", + core, + }); + await updateBooleanInputValue({ + boolean: false, + componentName: "/h2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq(`, ${d}`); + expect(stateVariables["/p2"].stateValues.text).eq(`${c}, ${d}`); + + await updateBooleanInputValue({ + boolean: false, + componentName: "/h1", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/h2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq(`${c}, `); + expect(stateVariables["/p2"].stateValues.text).eq(`${c}, ${d}`); + }); + + it("string and blank strings in options", async () => { + let core = await createTestCore({ + doenetML: ` + + foxjumps + elephanttrumpets + + +

a:

+ +

a1: $a{assignNames="a11 a12 a13 a14"}

+ +

pieces: +

q,r =

+ + +

q2 = $q

+

r2 = $r

+ + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let replacements = + stateVariables[ + stateVariables["/select1"].replacements![0].componentName + ].replacements!; + + let p1 = replacements[1].componentName; + let p2 = replacements[3].componentName; + let p3 = replacements[5].componentName; + + expect(stateVariables[p1].stateValues.text).eq(`q,r = ab`); + expect(stateVariables[p2].stateValues.text).eq(`q2 = a`); + expect(stateVariables[p3].stateValues.text).eq(`r2 = b`); + }); + + it("display error when miss a name in selectForVariants, inside text", async () => { + let core = await createTestCore({ + doenetML: ` + + +

We have a !

+ `, + }); + + let errorWarnings = core.errorWarnings; + + expect(errorWarnings.errors.length).eq(1); + expect(errorWarnings.warnings.length).eq(0); + + expect(errorWarnings.errors[0].message).contain( + "Some variants are specified for select but no options are specified for possible variant name: banana", + ); + expect(errorWarnings.errors[0].doenetMLrange.lineBegin).eq(4); + expect(errorWarnings.errors[0].doenetMLrange.charBegin).eq(24); + expect(errorWarnings.errors[0].doenetMLrange.lineEnd).eq(7); + expect(errorWarnings.errors[0].doenetMLrange.charEnd).eq(13); + }); + + it("display error when repeat name in selectForVariants more times than numToSelect, inside p", async () => { + let core = await createTestCore({ + doenetML: ` + + +

We have a !

+ `, + }); + + let errorWarnings = core.errorWarnings; + + expect(errorWarnings.errors.length).eq(1); + expect(errorWarnings.warnings.length).eq(0); + + expect(errorWarnings.errors[0].message).contain( + "Invalid variant name for select. Variant name apple appears in 2 options but number to select is 1", + ); + expect(errorWarnings.errors[0].doenetMLrange.lineBegin).eq(4); + expect(errorWarnings.errors[0].doenetMLrange.charBegin).eq(18); + expect(errorWarnings.errors[0].doenetMLrange.lineEnd).eq(7); + expect(errorWarnings.errors[0].doenetMLrange.charEnd).eq(13); + }); + + it("display error when repeat name in selectForVariants more times than numToSelect, inside document", async () => { + let core = await createTestCore({ + doenetML: ` + + + We have a ! + `, + }); + + let errorWarnings = core.errorWarnings; + + expect(errorWarnings.errors.length).eq(1); + expect(errorWarnings.warnings.length).eq(0); + + expect(errorWarnings.errors[0].message).contain( + "Variant name donut that is specified for select is not a possible variant name", + ); + expect(errorWarnings.errors[0].doenetMLrange.lineBegin).eq(4); + expect(errorWarnings.errors[0].doenetMLrange.charBegin).eq(15); + expect(errorWarnings.errors[0].doenetMLrange.lineEnd).eq(8); + expect(errorWarnings.errors[0].doenetMLrange.charEnd).eq(13); + }); + + it("display error when numToSelect is larger than number of options, inside graph", async () => { + let core = await createTestCore({ + doenetML: ` +

No points for graph!

+ + + `, + }); + + let errorWarnings = core.errorWarnings; + + expect(errorWarnings.errors.length).eq(1); + expect(errorWarnings.warnings.length).eq(0); + + expect(errorWarnings.errors[0].message).contain( + "Cannot select 3 components from only 2", + ); + expect(errorWarnings.errors[0].doenetMLrange.lineBegin).eq(4); + expect(errorWarnings.errors[0].doenetMLrange.charBegin).eq(12); + expect(errorWarnings.errors[0].doenetMLrange.lineEnd).eq(7); + expect(errorWarnings.errors[0].doenetMLrange.charEnd).eq(13); + }); + + it("numToSelect from selectFromSequence", async () => { + let core = await createTestCore({ + doenetML: ` +

n1 =

+

vars =

+

a1=$a1, b1=$b1, c1=$c1, d1=$d1, e1=$e1

+ +

n2 =

+

vars =

+

a2=$a2, b2=$b2, c2=$c2, d2=$d2, e2=$e2

+ +

n3 =

+

vars =

+

a3=$a3, b3=$b3, c3=$c3, d3=$d3, e3=$e3

+ +

n4 =

+

vars =

+

a4=$a4, b4=$b4, c4=$c4, d4=$d4, e4=$e4

+ +

n5 =

+

vars =

+

a5=$a5, b5=$b5, c5=$c5, d5=$d5, e5=$e5

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let n1 = stateVariables["/n1"].stateValues.value; + let n2 = stateVariables["/n2"].stateValues.value; + let n3 = stateVariables["/n3"].stateValues.value; + let n4 = stateVariables["/n4"].stateValues.value; + let n5 = stateVariables["/n5"].stateValues.value; + + let vars1 = stateVariables["/vars1"].replacements!.map( + (x) => + stateVariables[ + stateVariables[x.componentName].replacements![0] + .componentName + ].stateValues.value, + ); + let vars2 = stateVariables["/vars2"].replacements!.map( + (x) => + stateVariables[ + stateVariables[x.componentName].replacements![0] + .componentName + ].stateValues.value, + ); + let vars3 = stateVariables["/vars3"].replacements!.map( + (x) => + stateVariables[ + stateVariables[x.componentName].replacements![0] + .componentName + ].stateValues.value, + ); + let vars4 = stateVariables["/vars4"].replacements!.map( + (x) => + stateVariables[ + stateVariables[x.componentName].replacements![0] + .componentName + ].stateValues.value, + ); + let vars5 = stateVariables["/vars5"].replacements!.map( + (x) => + stateVariables[ + stateVariables[x.componentName].replacements![0] + .componentName + ].stateValues.value, + ); + + expect(vars1.length).eq(n1); + expect(vars2.length).eq(n2); + expect(vars3.length).eq(n3); + expect(vars4.length).eq(n4); + expect(vars5.length).eq(n5); + + vars1.length = 5; + vars2.length = 5; + vars3.length = 5; + vars4.length = 5; + vars5.length = 5; + + vars1.fill("", n1); + vars2.fill("", n2); + vars3.fill("", n3); + vars4.fill("", n4); + vars5.fill("", n5); + + let l = ["a", "b", "c", "d", "e"]; + + expect(stateVariables["/p1"].stateValues.text).eq( + vars1.map((v, i) => `${l[i]}1=${v}`).join(", "), + ); + expect(stateVariables["/p2"].stateValues.text).eq( + vars2.map((v, i) => `${l[i]}2=${v}`).join(", "), + ); + expect(stateVariables["/p3"].stateValues.text).eq( + vars3.map((v, i) => `${l[i]}3=${v}`).join(", "), + ); + expect(stateVariables["/p4"].stateValues.text).eq( + vars4.map((v, i) => `${l[i]}4=${v}`).join(", "), + ); + expect(stateVariables["/p5"].stateValues.text).eq( + vars5.map((v, i) => `${l[i]}5=${v}`).join(", "), + ); + }); + + it("add level to assign names even in shadow", async () => { + let core = await createTestCore({ + doenetML: ` +

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let q = stateVariables["/q"].stateValues.value.tree; + + expect(stateVariables["/c/q"].stateValues.value.tree).eq(q); + }); + + it("ensure unique names", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let pNames1 = stateVariables["/_select1"].replacements!.map( + (x) => + stateVariables[x.componentName].replacements![0].componentName, + ); + for (let pn of pNames1) { + expect(stateVariables[pn].stateValues.text).eq("What is this?"); + } + + let pNames2 = ["/A", "/B", "/C"].map( + (x) => stateVariables[x].replacements![0].componentName, + ); + for (let pn of pNames2) { + expect(stateVariables[pn].stateValues.text).eq("What is this?"); + } + + for (let pn of ["/D", "/E", "/F"]) { + expect(stateVariables[pn].stateValues.text).eq("What is this?"); + } + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/selectfromsequence.test.ts b/packages/doenetml-worker/src/test/tagSpecific/selectfromsequence.test.ts new file mode 100644 index 000000000..113398753 --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/selectfromsequence.test.ts @@ -0,0 +1,1443 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { + updateBooleanInputValue, + updateMathInputValue, + updateTextInputValue, +} from "../utils/actions"; +import me from "math-expressions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +describe("SelectFromSequence tag tests", async () => { + async function test_values_separately({ + doenetML, + componentNames, + valid_values, + num_samples, + must_be_distinct = false, + is_math = false, + }: { + doenetML: string; + componentNames: string[]; + valid_values: any[][]; + num_samples: number; + must_be_distinct?: boolean; + is_math?: boolean; + }) { + for (let i = 0; i < num_samples; i++) { + let core = await createTestCore({ + doenetML, + requestedVariantIndex: i, + }); + const stateVariables = await returnAllStateVariables(core); + for (let [ind, name] of componentNames.entries()) { + let value = stateVariables[name].stateValues.value; + expect( + is_math + ? valid_values[ind].some((v) => v.equals(value)) + : valid_values[ind].includes(value), + ).eq(true, `Expected ${value} to be in ${valid_values[ind]}`); + } + + if (must_be_distinct) { + for (let name1 of componentNames) { + let val1 = stateVariables[name1].stateValues.value; + for (let name2 of componentNames) { + if (name2 !== name1) { + let val2 = stateVariables[name2].stateValues.value; + if (is_math) { + expect(val2.equals(val1)).eq(false); + } else { + expect(val2).not.eq(val1); + } + } + } + } + } + } + } + + async function test_combined_values({ + doenetML, + componentNames, + valid_combinations, + num_samples, + is_math = false, + }: { + doenetML: string; + componentNames: string[]; + valid_combinations: any[][]; + num_samples: number; + is_math?: boolean; + }) { + for (let i = 0; i < num_samples; i++) { + let core = await createTestCore({ + doenetML, + requestedVariantIndex: i, + }); + const stateVariables = await returnAllStateVariables(core); + let values = componentNames.map( + (name) => stateVariables[name].stateValues.value, + ); + + expect( + valid_combinations.some((comb) => + comb.every((v, i) => + is_math ? v.equals(values[i]) : v === values[i], + ), + ), + ).eq( + true, + `Expected (${values}) to be in ${valid_combinations.map((comb) => `(${comb})`)}`, + ); + } + } + + it("no parameters, select single number from 1 to 10", async () => { + const doenetML = ``; + const valid_values = [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]; + const componentNames = ["/res"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 30, + }); + }); + + it("select single number from 1 to 6", async () => { + const doenetML = ``; + const valid_values = [[1, 2, 3, 4, 5, 6]]; + const componentNames = ["/res"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 30, + }); + }); + + it("select single number from -3 to 5", async () => { + const doenetML = ``; + const valid_values = [[-3, -2, -1, 0, 1, 2, 3, 4, 5]]; + const componentNames = ["/res"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 30, + }); + }); + + it("select single number from -3 to 5, excluding 0", async () => { + const doenetML = ``; + const valid_values = [[-3, -2, -1, 1, 2, 3, 4, 5]]; + const componentNames = ["/res"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 30, + }); + }); + + it("select single odd number from -3 to 5", async () => { + const doenetML = ``; + const valid_values = [[-3, -1, 1, 3, 5]]; + const componentNames = ["/res"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 30, + }); + }); + + it("select single letter from c to h", async () => { + const doenetML = ``; + const valid_values = [["c", "d", "e", "f", "g", "h"]]; + const componentNames = ["/res"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 30, + }); + }); + + it("select two even numbers from -4 to 4, excluding 0", async () => { + const doenetML = ``; + const valid_values = [ + [-4, -2, 2, 4], + [-4, -2, 2, 4], + ]; + const componentNames = ["/res1", "/res2"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 30, + must_be_distinct: true, + }); + }); + + it("select two even numbers from -4 to 2, excluding 0 and combinations", async () => { + const doenetML = ``; + const valid_combinations = [ + [-4, 2], + [-2, -4], + [2, -2], + ]; + const componentNames = ["/res1", "/res2"]; + + await test_combined_values({ + doenetML, + valid_combinations, + componentNames, + num_samples: 10, + }); + }); + + it("select two even numbers from -4 to 2, excluding 0 and combinations, as copies", async () => { + const doenetML = ` + -4 -2 + -2 + 2 + -4 + -4 -2 + -2 2 + 2 -4 + +

`; + const valid_combinations = [ + [-4, 2], + [-2, -4], + [2, -2], + ]; + const componentNames = ["/res1", "/res2"]; + + await test_combined_values({ + doenetML, + valid_combinations, + componentNames, + num_samples: 10, + }); + }); + + it("select two even numbers from -4 to 2, excluding 0 and combinations, exclude extras", async () => { + const doenetML = ``; + const valid_combinations = [ + [-4, 2], + [-2, -4], + [2, -2], + ]; + const componentNames = ["/res1", "/res2"]; + + await test_combined_values({ + doenetML, + valid_combinations, + componentNames, + num_samples: 10, + }); + }); + + it("select three numbers from 1 to 3, exclude combinations with two 1s", async () => { + const doenetML = ``; + const valid_combinations = [ + [1, 2, 2], + [1, 2, 3], + [1, 3, 2], + [1, 3, 3], + [2, 1, 2], + [2, 1, 3], + [3, 1, 2], + [3, 1, 3], + [2, 2, 1], + [2, 3, 1], + [3, 2, 1], + [3, 3, 1], + [2, 2, 2], + [2, 2, 3], + [2, 3, 2], + [3, 2, 2], + [3, 3, 2], + [3, 2, 3], + [2, 3, 3], + [3, 3, 3], + ]; + const componentNames = ["/res1", "/res2", "/res3"]; + + await test_combined_values({ + doenetML, + valid_combinations, + componentNames, + num_samples: 10, + }); + }); + + it("select three numbers from 1 to 3, exclude combinations with two 1s, duplicate excludes", async () => { + const doenetML = ``; + const valid_combinations = [ + [1, 2, 2], + [1, 2, 3], + [1, 3, 2], + [1, 3, 3], + [2, 1, 2], + [2, 1, 3], + [3, 1, 2], + [3, 1, 3], + [2, 2, 1], + [2, 3, 1], + [3, 2, 1], + [3, 3, 1], + [2, 2, 2], + [2, 2, 3], + [2, 3, 2], + [3, 2, 2], + [3, 3, 2], + [3, 2, 3], + [2, 3, 3], + [3, 3, 3], + ]; + const componentNames = ["/res1", "/res2", "/res3"]; + + await test_combined_values({ + doenetML, + valid_combinations, + componentNames, + num_samples: 10, + }); + }); + + it("select four numbers from 0 to 3, exclude positions of each number", async () => { + const doenetML = ``; + const valid_values = [ + [1, 2, 3], + [0, 2, 3], + [0, 1, 3], + [0, 1, 2], + ]; + + const componentNames = ["/res1", "/res2", "/res3", "/res4"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 10, + }); + }); + + it("select three numbers from 1 to 3, without replacement exclude positions of each number", async () => { + const doenetML = ``; + const valid_values = [ + [2, 3], + [1, 3], + [1, 2], + ]; + + const componentNames = ["/res1", "/res2", "/res3"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 10, + must_be_distinct: true, + }); + }); + + it("display error when select three numbers from 1 to 3, without replacement, exclude any place for 1", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let errorWarnings = core.errorWarnings; + + expect(errorWarnings.errors.length).eq(1); + expect(errorWarnings.warnings.length).eq(0); + + expect(errorWarnings.errors[0].message).contain("Excluded over 70%"); + expect(errorWarnings.errors[0].doenetMLrange.lineBegin).eq(2); + expect(errorWarnings.errors[0].doenetMLrange.charBegin).eq(8); + expect(errorWarnings.errors[0].doenetMLrange.lineEnd).eq(2); + expect(errorWarnings.errors[0].doenetMLrange.charEnd).eq(122); + }); + + it("select 10 numbers from 1 to 10, without replacement, exclude positions of each number", async () => { + // make sure that exclude combinations does not enumerate all combinations excluded + // to count them + const doenetML = ``; + let allNumbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + const valid_values: number[][] = []; + + for (let j = 0; j < 10; j++) { + let validNs = [...allNumbers]; + validNs.splice(j, 1); + valid_values.push(validNs); + } + + const componentNames = [ + "/res1", + "/res2", + "/res3", + "/res4", + "/res5", + "/res6", + "/res7", + "/res8", + "/res9", + "/res10", + ]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 5, + must_be_distinct: true, + }); + }); + + it("select five even numbers with replacement from -4 to 4, excluding 0", async () => { + const doenetML = ``; + const valid_values = [ + [-4, -2, 2, 4], + [-4, -2, 2, 4], + [-4, -2, 2, 4], + [-4, -2, 2, 4], + [-4, -2, 2, 4], + ]; + + const componentNames = ["/res1", "/res2", "/res3", "/res4", "/res5"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 10, + }); + }); + + it("select five (number initially unresolved) even numbers with replacement from -4 to 4, excluding 0", async () => { + const doenetML = ` + + $n3{name="n2"} + $num1{name="n"} + $n2+$num2+2 + $n3+$num3 + $num3{name="n3"} + 1`; + + const valid_values = [ + [-4, -2, 2, 4], + [-4, -2, 2, 4], + [-4, -2, 2, 4], + [-4, -2, 2, 4], + [-4, -2, 2, 4], + ]; + + const componentNames = ["/res1", "/res2", "/res3", "/res4", "/res5"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 3, + }); + }); + + it("asList", async () => { + let core = await createTestCore({ + doenetML: ` +

+

+ + `, + }); + + let results: number[] = []; + + let stateVariables = await returnAllStateVariables(core); + + results.push(stateVariables["/u"].stateValues.value); + results.push(stateVariables["/v"].stateValues.value); + results.push(stateVariables["/w"].stateValues.value); + results.push(stateVariables["/x"].stateValues.value); + results.push(stateVariables["/y"].stateValues.value); + + for (let num of results) { + expect(num).gte(175).lte(205); + } + expect(stateVariables["/p1"].stateValues.text).eq(results.join(", ")); + expect(stateVariables["/p2"].stateValues.text).eq(results.join("")); + }); + + it("copies don't resample", async () => { + let core = await createTestCore({ + doenetML: ` +

+ + +

+ +

+ $sample1{name="noresample1"} + $sample2{name="noresample2"} + $noresample1{name="noreresample1"} + $noresample2{name="noreresample2"} +

+ +

+ +

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + let num1 = stateVariables["/n1"].stateValues.value; + let num2 = stateVariables["/n2"].stateValues.value; + expect(Number.isInteger(num1) && num1 >= 1 && num1 <= 100).eq(true); + expect(Number.isInteger(num2) && num2 >= 1 && num2 <= 100).eq(true); + expect( + stateVariables[ + stateVariables["/noresample1"].replacements![0].componentName + ].stateValues.value, + ).eq(num1); + expect( + stateVariables[ + stateVariables["/noresample2"].replacements![0].componentName + ].stateValues.value, + ).eq(num2); + expect( + stateVariables[ + stateVariables["/noreresample1"].replacements![0].componentName + ].stateValues.value, + ).eq(num1); + expect( + stateVariables[ + stateVariables["/noreresample2"].replacements![0].componentName + ].stateValues.value, + ).eq(num2); + + expect( + stateVariables[ + stateVariables["/noresamplep"].activeChildren[1].componentName + ].stateValues.value, + ).eq(num1); + expect( + stateVariables[ + stateVariables["/noresamplep"].activeChildren[3].componentName + ].stateValues.value, + ).eq(num2); + expect( + stateVariables[ + stateVariables["/noreresamplep"].activeChildren[1].componentName + ].stateValues.value, + ).eq(num1); + expect( + stateVariables[ + stateVariables["/noreresamplep"].activeChildren[3].componentName + ].stateValues.value, + ).eq(num2); + }); + + it("select doesn't change dynamically", async () => { + let core = await createTestCore({ + doenetML: ` + + +

+ +

+ + + +

+ +

+

$maxNum2.value{assignNames="maxNum2a"}

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let sample1replacements = stateVariables["/sample1"].replacements!; + let sample2replacements = stateVariables["/sample2"].replacements!; + expect(sample1replacements.length).eq(5); + expect(sample2replacements.length).eq(2); + let sample1numbers = sample1replacements.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let sample2numbers = sample2replacements.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + + for (let num of sample1numbers) { + expect([1, 2, 3].includes(num)).eq(true); + } + for (let num of sample2numbers) { + expect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10].includes(num)).eq(true); + } + + // Nothing changes when change mathInputs + await updateMathInputValue({ + latex: "7", + componentName: "/numToSelect", + core, + }); + await updateMathInputValue({ + latex: "11", + componentName: "/maxNum", + core, + }); + await updateMathInputValue({ + latex: "16", + componentName: "/numToSelect2", + core, + }); + await updateMathInputValue({ + latex: "18", + componentName: "/maxNum2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + sample1replacements = stateVariables["/sample1"].replacements!; + sample2replacements = stateVariables["/sample2"].replacements!; + + expect( + sample1replacements.map( + (x) => stateVariables[x.componentName].stateValues.value, + ), + ).eqls(sample1numbers); + expect( + sample2replacements.map( + (x) => stateVariables[x.componentName].stateValues.value, + ), + ).eqls(sample2numbers); + }); + + it("select doesn't resample in dynamic map", async () => { + let core = await createTestCore({ + doenetML: ` + How many numbers do you want? +

+ + + + +

+ +

$map1

+ + $p1{name="p3"} + $p2{name="p4"} + + $p3{name="p5"} + $p4{name="p6"} + `, + }); + + async function check_sampled_numbers(sampledNumbers: number[]) { + const stateVariables = await returnAllStateVariables(core); + + expect( + stateVariables["/p1"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + + expect( + stateVariables["/p2"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + + expect( + stateVariables["/p3"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + + expect( + stateVariables["/p4"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + + expect( + stateVariables["/p5"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + + expect( + stateVariables["/p6"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + } + + let sampledNumbers: number[] = []; + + // initially nothing + await check_sampled_numbers([]); + + // sample one variable + await updateMathInputValue({ latex: "1", componentName: "/mi1", core }); + + let stateVariables = await returnAllStateVariables(core); + sampledNumbers.push(stateVariables["/a/n"].stateValues.value); + await check_sampled_numbers(sampledNumbers); + + // go back to nothing + await updateMathInputValue({ latex: "0", componentName: "/mi1", core }); + await check_sampled_numbers([]); + + // get same number back + await updateMathInputValue({ latex: "1", componentName: "/mi1", core }); + await check_sampled_numbers(sampledNumbers); + + // get two more samples + await updateMathInputValue({ latex: "3", componentName: "/mi1", core }); + + stateVariables = await returnAllStateVariables(core); + let n1 = stateVariables["/a/n"].stateValues.value; + let n2 = stateVariables["/b/n"].stateValues.value; + let n3 = stateVariables["/c/n"].stateValues.value; + expect(n1).eq(sampledNumbers[0]); + sampledNumbers.push(n2); + sampledNumbers.push(n3); + await check_sampled_numbers(sampledNumbers); + + // go back to nothing + await updateMathInputValue({ latex: "0", componentName: "/mi1", core }); + await check_sampled_numbers([]); + + // get first two numbers back + await updateMathInputValue({ latex: "2", componentName: "/mi1", core }); + await check_sampled_numbers(sampledNumbers.slice(0, 2)); + + // get six total samples + await updateMathInputValue({ latex: "6", componentName: "/mi1", core }); + + stateVariables = await returnAllStateVariables(core); + n1 = stateVariables["/a/n"].stateValues.value; + n2 = stateVariables["/b/n"].stateValues.value; + n3 = stateVariables["/c/n"].stateValues.value; + let n4 = stateVariables["/d/n"].stateValues.value; + let n5 = stateVariables["/e/n"].stateValues.value; + let n6 = stateVariables["/f/n"].stateValues.value; + expect(n1).eq(sampledNumbers[0]); + expect(n2).eq(sampledNumbers[1]); + expect(n3).eq(sampledNumbers[2]); + sampledNumbers.push(n4); + sampledNumbers.push(n5); + sampledNumbers.push(n6); + await check_sampled_numbers(sampledNumbers); + + // go back to nothing + await updateMathInputValue({ latex: "0", componentName: "/mi1", core }); + await check_sampled_numbers([]); + + // get all six back + await updateMathInputValue({ latex: "6", componentName: "/mi1", core }); + await check_sampled_numbers(sampledNumbers); + }); + + it("select single math", async () => { + const doenetML = ``; + const valid_values = [ + [me.fromText("x"), me.fromText("x+y"), me.fromText("x+2y")], + ]; + const componentNames = ["/res"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 3, + is_math: true, + }); + }); + + it("select multiple maths", async () => { + const doenetML = ``; + const valid_values = [ + [me.fromText("x"), me.fromText("x+y"), me.fromText("x+2y")], + [me.fromText("x"), me.fromText("x+y"), me.fromText("x+2y")], + [me.fromText("x"), me.fromText("x+y"), me.fromText("x+2y")], + ]; + const componentNames = ["/res1", "/res2", "/res3"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 3, + is_math: true, + must_be_distinct: true, + }); + }); + + it("select multiple maths, new namespace", async () => { + const doenetML = ``; + const valid_values = [ + [me.fromText("x"), me.fromText("x+y"), me.fromText("x+2y")], + [me.fromText("x"), me.fromText("x+y"), me.fromText("x+2y")], + [me.fromText("x"), me.fromText("x+y"), me.fromText("x+2y")], + ]; + const componentNames = ["/s/res1", "/s/res2", "/s/res3"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 3, + is_math: true, + must_be_distinct: true, + }); + }); + + it("selectFromSequence with hide will hide replacements", async () => { + let core = await createTestCore({ + doenetML: ` +

,

+

$c, $d{hide="false"}

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let c = await stateVariables["/c"].stateValues.value; + let d = await stateVariables["/d"].stateValues.value; + expect(["a", "b", "c", "d", "e"].includes(c)).eq(true); + expect(["a", "b", "c", "d", "e"].includes(d)).eq(true); + + expect(stateVariables["/p1"].stateValues.text).eq(`${c}, `); + expect(stateVariables["/p2"].stateValues.text).eq(`${c}, ${d}`); + }); + + it("select multiple numbers with excludeCombinations, handles round-off error", async () => { + // Third number selected will be 0.1*3, which isn't exactly 0.3 due to round off error. + // Even so, excluding 0.3 works successfully. + const doenetML = ``; + const valid_combinations = [ + [0.1, 0.2], + [0.2, 0.1], + [0.1 * 3, 0.2], + ]; + const componentNames = ["/res1", "/res2"]; + + await test_combined_values({ + doenetML, + valid_combinations, + componentNames, + num_samples: 10, + }); + }); + + it("select multiple maths with excludeCombinations, handles round-off error", async () => { + // Third number selected will be 0.1*3, which isn't exactly 0.3 due to round off error. + // Even so, excluding 0.3 works successfully. + const doenetML = ``; + const valid_combinations = [ + [me.fromAst(0.1), me.fromAst(0.2)], + [me.fromAst(0.2), me.fromAst(0.1)], + [me.fromAst(0.3), me.fromAst(0.2)], + ]; + const componentNames = ["/res1", "/res2"]; + + await test_combined_values({ + doenetML, + valid_combinations, + componentNames, + num_samples: 10, + is_math: true, + }); + }); + + it("select multiple maths with excludes and excludeCombinations", async () => { + const doenetML = ``; + const valid_combinations = [ + [me.fromText("x"), me.fromText("x+3y")], + [me.fromText("x+y"), me.fromText("x")], + [me.fromText("x+3y"), me.fromText("x+y")], + ]; + const componentNames = ["/res1", "/res2"]; + + await test_combined_values({ + doenetML, + valid_combinations, + componentNames, + num_samples: 10, + is_math: true, + }); + }); + + it("select multiple maths with excludes and excludeCombinations, as copies", async () => { + const doenetML = ` + x x+y + x+y + x+3y + x + x x+y + x+y x+3y + `; + const valid_combinations = [ + [me.fromText("x"), me.fromText("x+3y")], + [me.fromText("x+y"), me.fromText("x")], + [me.fromText("x+3y"), me.fromText("x+y")], + ]; + const componentNames = ["/res1", "/res2"]; + + await test_combined_values({ + doenetML, + valid_combinations, + componentNames, + num_samples: 10, + is_math: true, + }); + }); + + it("select multiple maths with excludes and excludeCombinations, exclude extras", async () => { + const doenetML = ``; + const valid_combinations = [ + [me.fromText("x"), me.fromText("x+3y")], + [me.fromText("x+y"), me.fromText("x")], + [me.fromText("x+3y"), me.fromText("x+y")], + ]; + const componentNames = ["/res1", "/res2"]; + + await test_combined_values({ + doenetML, + valid_combinations, + componentNames, + num_samples: 10, + is_math: true, + }); + }); + + it("select multiple letters with excludes and excludeCombinations", async () => { + const doenetML = ``; + const valid_combinations = [ + ["m", "s"], + ["s", "v"], + ["v", "m"], + ]; + const componentNames = ["/res1", "/res2"]; + + await test_combined_values({ + doenetML, + valid_combinations, + componentNames, + num_samples: 10, + }); + }); + + it("select multiple letters with excludes and excludeCombinations, as copies", async () => { + const doenetML = ` + m v + s + v + s + m v + s m + `; + const valid_combinations = [ + ["m", "s"], + ["s", "v"], + ["v", "m"], + ]; + const componentNames = ["/res1", "/res2"]; + + await test_combined_values({ + doenetML, + valid_combinations, + componentNames, + num_samples: 10, + }); + }); + + it("select multiple letters with excludes and excludeCombinations, exclude extras", async () => { + const doenetML = ``; + const valid_combinations = [ + ["m", "s"], + ["s", "v"], + ["v", "m"], + ]; + const componentNames = ["/res1", "/res2"]; + + await test_combined_values({ + doenetML, + valid_combinations, + componentNames, + num_samples: 10, + }); + }); + + it("select numbers and sort", async () => { + let core = await createTestCore({ + doenetML: ` +

+ + $p1{name="p2"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let originalNumbers = stateVariables["/p1"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let secondNumbers = stateVariables["/p2"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + + expect([...originalNumbers].sort((a, b) => a - b)).eqls( + originalNumbers, + ); + expect(secondNumbers).eqls(originalNumbers); + }); + + it("select letters and sort", async () => { + let core = await createTestCore({ + doenetML: ` +

+ + $p1{name="p2"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let originalNumbers = stateVariables["/p1"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let secondNumbers = stateVariables["/p2"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + + function compare_letters(a: string, b: string) { + // shorter letter combinations are sorted before longer ones + if (a.length === b.length) { + if (a < b) { + return -1; + } else if (a > b) { + return 1; + } else { + return 0; + } + } else { + return a.length - b.length; + } + } + expect([...originalNumbers].sort(compare_letters)).eqls( + originalNumbers, + ); + expect(secondNumbers).eqls(originalNumbers); + }); + + // Note: this test encodes undesired behavior (see issue #246) + // When this issue is resolved, change this test to make sure the references + // are hidden when the selectFromSequence is hidden + it("selectFromSequence hides dynamically", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + +

,

+

$c, $d

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let c = await stateVariables["/c"].stateValues.value; + let d = await stateVariables["/d"].stateValues.value; + expect(["a", "b", "c", "d", "e"].includes(c)).eq(true); + expect(["a", "b", "c", "d", "e"].includes(d)).eq(true); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq(`${c}, `); + expect(stateVariables["/p2"].stateValues.text).eq(`${c}, ${d}`); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/h1", + core, + }); + await updateBooleanInputValue({ + boolean: false, + componentName: "/h2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq(`, ${d}`); + expect(stateVariables["/p2"].stateValues.text).eq(`${c}, ${d}`); + + await updateBooleanInputValue({ + boolean: false, + componentName: "/h1", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/h2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq(`${c}, `); + expect(stateVariables["/p2"].stateValues.text).eq(`${c}, ${d}`); + }); + + it("selectFromSequence defaults to fixed", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + +

+ + + +

+

+ $a{name="a2"} + $b{name="b2"} + $c{name="c2"} +

+

+ $a + $b + $c +

+

+ $a2 + $b2 + $c2 +

+

+ $a.fixed{assignNames="af"} + $b.fixed{assignNames="bf"} + $c.fixed{assignNames="cf"} +

+

+ $a2.fixed{assignNames="a2f"} + $b2.fixed{assignNames="b2f"} + $c2.fixed{assignNames="c2f"} +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let a = stateVariables["/a"].stateValues.value; + let b = stateVariables["/b"].stateValues.value; + let c = stateVariables["/c"].stateValues.value; + expect(["a", "b", "c", "d", "e"].includes(a)).eq(true); + expect(["a", "b", "c", "d", "e"].includes(b)).eq(true); + expect(["a", "b", "c", "d", "e"].includes(c)).eq(true); + + expect(stateVariables["/a2"].stateValues.value).eq(a); + expect(stateVariables["/b2"].stateValues.value).eq(b); + expect(stateVariables["/c2"].stateValues.value).eq(c); + + expect(stateVariables["/af"].stateValues.value).eq(true); + expect(stateVariables["/bf"].stateValues.value).eq(false); + expect(stateVariables["/cf"].stateValues.value).eq(true); + expect(stateVariables["/a2f"].stateValues.value).eq(true); + expect(stateVariables["/b2f"].stateValues.value).eq(false); + expect(stateVariables["/c2f"].stateValues.value).eq(true); + + await updateTextInputValue({ text: "f", componentName: "/a3", core }); + await updateTextInputValue({ text: "g", componentName: "/b3", core }); + await updateTextInputValue({ text: "h", componentName: "/c3", core }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.value).eq(a); + expect(stateVariables["/b"].stateValues.value).eq("g"); + expect(stateVariables["/c"].stateValues.value).eq(c); + expect(stateVariables["/a2"].stateValues.value).eq(a); + expect(stateVariables["/b2"].stateValues.value).eq("g"); + expect(stateVariables["/c2"].stateValues.value).eq(c); + + await updateTextInputValue({ text: "i", componentName: "/a4", core }); + await updateTextInputValue({ text: "j", componentName: "/b4", core }); + await updateTextInputValue({ text: "k", componentName: "/c4", core }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.value).eq(a); + expect(stateVariables["/b"].stateValues.value).eq("j"); + expect(stateVariables["/c"].stateValues.value).eq(c); + expect(stateVariables["/a2"].stateValues.value).eq(a); + expect(stateVariables["/b2"].stateValues.value).eq("j"); + expect(stateVariables["/c2"].stateValues.value).eq(c); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/f1", + core, + }); + await updateBooleanInputValue({ + boolean: false, + componentName: "/f2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/af"].stateValues.value).eq(true); + expect(stateVariables["/bf"].stateValues.value).eq(true); + expect(stateVariables["/cf"].stateValues.value).eq(false); + expect(stateVariables["/a2f"].stateValues.value).eq(true); + expect(stateVariables["/b2f"].stateValues.value).eq(true); + expect(stateVariables["/c2f"].stateValues.value).eq(false); + + await updateTextInputValue({ text: "l", componentName: "/a3", core }); + await updateTextInputValue({ text: "m", componentName: "/b3", core }); + await updateTextInputValue({ text: "n", componentName: "/c3", core }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.value).eq(a); + expect(stateVariables["/b"].stateValues.value).eq("j"); + expect(stateVariables["/c"].stateValues.value).eq("n"); + expect(stateVariables["/a2"].stateValues.value).eq(a); + expect(stateVariables["/b2"].stateValues.value).eq("j"); + expect(stateVariables["/c2"].stateValues.value).eq("n"); + + await updateTextInputValue({ text: "o", componentName: "/a4", core }); + await updateTextInputValue({ text: "p", componentName: "/b4", core }); + await updateTextInputValue({ text: "q", componentName: "/c4", core }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/a"].stateValues.value).eq(a); + expect(stateVariables["/b"].stateValues.value).eq("j"); + expect(stateVariables["/c"].stateValues.value).eq("q"); + expect(stateVariables["/a2"].stateValues.value).eq(a); + expect(stateVariables["/b2"].stateValues.value).eq("j"); + expect(stateVariables["/c2"].stateValues.value).eq("q"); + }); + + it("numToSelect from selectFromSequence", async () => { + let core = await createTestCore({ + doenetML: ` +

n1 =

+

nums =

+

a1=$a1, b1=$b1, c1=$c1, d1=$d1, e1=$e1

+ +

n2 =

+

nums =

+

a2=$a2, b2=$b2, c2=$c2, d2=$d2, e2=$e2

+ +

n3 =

+

nums =

+

a3=$a3, b3=$b3, c3=$c3, d3=$d3, e3=$e3

+ +

n4 =

+

nums =

+

a4=$a4, b4=$b4, c4=$c4, d4=$d4, e4=$e4

+ +

n5 =

+

nums =

+

a5=$a5, b5=$b5, c5=$c5, d5=$d5, e5=$e5

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let n1 = stateVariables["/n1"].stateValues.value; + let n2 = stateVariables["/n2"].stateValues.value; + let n3 = stateVariables["/n3"].stateValues.value; + let n4 = stateVariables["/n4"].stateValues.value; + let n5 = stateVariables["/n5"].stateValues.value; + + let nums1 = stateVariables["/nums1"].replacements!.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let nums2 = stateVariables["/nums2"].replacements!.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let nums3 = stateVariables["/nums3"].replacements!.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let nums4 = stateVariables["/nums4"].replacements!.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let nums5 = stateVariables["/nums5"].replacements!.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + + expect(nums1.length).eq(n1); + expect(nums2.length).eq(n2); + expect(nums3.length).eq(n3); + expect(nums4.length).eq(n4); + expect(nums5.length).eq(n5); + + nums1.length = 5; + nums2.length = 5; + nums3.length = 5; + nums4.length = 5; + nums5.length = 5; + + nums1.fill("", n1); + nums2.fill("", n2); + nums3.fill("", n3); + nums4.fill("", n4); + nums5.fill("", n5); + + let l = ["a", "b", "c", "d", "e"]; + + expect(stateVariables["/p1"].stateValues.text).eq( + nums1.map((v, i) => `${l[i]}1=${v}`).join(", "), + ); + expect(stateVariables["/p2"].stateValues.text).eq( + nums2.map((v, i) => `${l[i]}2=${v}`).join(", "), + ); + expect(stateVariables["/p3"].stateValues.text).eq( + nums3.map((v, i) => `${l[i]}3=${v}`).join(", "), + ); + expect(stateVariables["/p4"].stateValues.text).eq( + nums4.map((v, i) => `${l[i]}4=${v}`).join(", "), + ); + expect(stateVariables["/p5"].stateValues.text).eq( + nums5.map((v, i) => `${l[i]}5=${v}`).join(", "), + ); + }); + + it("rounding", async () => { + let core = await createTestCore({ + doenetML: ` +

+

+

+

+ +

$n1

+

$n2

+

$n3

+

$n4

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let n1 = stateVariables["/n1"].stateValues.value; + let n2 = stateVariables["/n2"].stateValues.value; + let n3 = stateVariables["/n3"].stateValues.value; + let n4 = stateVariables["/n4"].stateValues.value; + + expect(stateVariables["/n1"].stateValues.text).eq( + String(Math.round(n1 * 10 ** 8) / 10 ** 8), + ); + expect(stateVariables["/n2"].stateValues.text).eq( + String(Math.round(n2 * 10 ** 1) / 10 ** 1), + ); + expect(stateVariables["/n3"].stateValues.text).eq( + String(Math.round(n3 * 10 ** 3) / 10 ** 3), + ); + expect(stateVariables["/n4"].stateValues.text).eq(String(n4) + ".0"); + + expect(stateVariables["/n1a"].stateValues.text).eq( + String(Math.round(n1 * 10 ** 8) / 10 ** 8), + ); + expect(stateVariables["/n2a"].stateValues.text).eq( + String(Math.round(n2 * 10 ** 1) / 10 ** 1), + ); + expect(stateVariables["/n3a"].stateValues.text).eq( + String(Math.round(n3 * 10 ** 3) / 10 ** 3), + ); + expect(stateVariables["/n4a"].stateValues.text).eq(String(n4) + ".0"); + }); + + it("display error when select 3 from 1, inside text", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let errorWarnings = core.errorWarnings; + + expect(errorWarnings.errors.length).eq(1); + expect(errorWarnings.warnings.length).eq(0); + + expect(errorWarnings.errors[0].message).contain( + "Cannot select 3 values from a sequence of length 1", + ); + expect(errorWarnings.errors[0].doenetMLrange.lineBegin).eq(2); + expect(errorWarnings.errors[0].doenetMLrange.charBegin).eq(17); + expect(errorWarnings.errors[0].doenetMLrange.lineEnd).eq(2); + expect(errorWarnings.errors[0].doenetMLrange.charEnd).eq(65); + }); + + it("check bugfix for non-constant exclude and unique variants", async () => { + let core = await createTestCore({ + doenetML: ` + +

Number to exclude: 2

+

+ +

$n

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let n = stateVariables["/n"].stateValues.value; + + expect(stateVariables["/n"].stateValues.value).eq(n); + + expect(stateVariables["/na"].stateValues.value).eq(n); + + expect(n === 1 || n === 3).eq(true); + }); + + it("check bugfix for non-constant exclude and defaulting to unique variants", async () => { + let core = await createTestCore({ + doenetML: ` +

Number to exclude: 2

+

+ +

$n

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let n = stateVariables["/n"].stateValues.value; + + expect(stateVariables["/n"].stateValues.value).eq(n); + + expect(stateVariables["/na"].stateValues.value).eq(n); + + expect(n === 1 || n === 3).eq(true); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/selectprimenumbers.test.ts b/packages/doenetml-worker/src/test/tagSpecific/selectprimenumbers.test.ts new file mode 100644 index 000000000..8f07d0471 --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/selectprimenumbers.test.ts @@ -0,0 +1,976 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { + updateBooleanInputValue, + updateMathInputValue, +} from "../utils/actions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +describe("selectPrimeNumbers tag tests", async () => { + async function test_values_separately({ + doenetML, + componentNames, + valid_values, + num_samples, + must_be_distinct = false, + is_math = false, + }: { + doenetML: string; + componentNames: string[]; + valid_values: any[][]; + num_samples: number; + must_be_distinct?: boolean; + is_math?: boolean; + }) { + for (let i = 0; i < num_samples; i++) { + let core = await createTestCore({ + doenetML, + requestedVariantIndex: i, + }); + const stateVariables = await returnAllStateVariables(core); + for (let [ind, name] of componentNames.entries()) { + let value = stateVariables[name].stateValues.value; + expect( + is_math + ? valid_values[ind].some((v) => v.equals(value)) + : valid_values[ind].includes(value), + ).eq(true, `Expected ${value} to be in ${valid_values[ind]}`); + } + + if (must_be_distinct) { + for (let name1 of componentNames) { + let val1 = stateVariables[name1].stateValues.value; + for (let name2 of componentNames) { + if (name2 !== name1) { + let val2 = stateVariables[name2].stateValues.value; + if (is_math) { + expect(val2.equals(val1)).eq(false); + } else { + expect(val2).not.eq(val1); + } + } + } + } + } + } + } + + async function test_combined_values({ + doenetML, + componentNames, + valid_combinations, + num_samples, + is_math = false, + }: { + doenetML: string; + componentNames: string[]; + valid_combinations: any[][]; + num_samples: number; + is_math?: boolean; + }) { + for (let i = 0; i < num_samples; i++) { + let core = await createTestCore({ + doenetML, + requestedVariantIndex: i, + }); + const stateVariables = await returnAllStateVariables(core); + let values = componentNames.map( + (name) => stateVariables[name].stateValues.value, + ); + + expect( + valid_combinations.some((comb) => + comb.every((v, i) => + is_math ? v.equals(values[i]) : v === values[i], + ), + ), + ).eq( + true, + `Expected (${values}) to be in ${valid_combinations.map((comb) => `(${comb})`)}`, + ); + } + } + + it("no parameters, select single prime number from 2 to 100", async () => { + const doenetML = ``; + const valid_values = [ + [ + 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, + 61, 67, 71, 73, 79, 83, 89, 97, + ], + ]; + const componentNames = ["/res"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 30, + }); + }); + + it("select single prime number from 2 to 6", async () => { + const doenetML = ``; + const valid_values = [[2, 3, 5]]; + const componentNames = ["/res"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 30, + }); + }); + + it("select single prime number from 9 to 39", async () => { + const doenetML = ``; + const valid_values = [[11, 13, 17, 19, 23, 29, 31, 37]]; + const componentNames = ["/res"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 30, + }); + }); + + it("select single prime number from 9 to 39, excluding 19", async () => { + const doenetML = ``; + const valid_values = [[11, 13, 17, 23, 29, 31, 37]]; + const componentNames = ["/res"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 30, + }); + }); + + it("select two prime numbers from 1020 to 1050, excluding 1031 and 1049", async () => { + const doenetML = ``; + const valid_values = [ + [1021, 1033, 1039], + [1021, 1033, 1039], + ]; + const componentNames = ["/res1", "/res2"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 10, + must_be_distinct: true, + }); + }); + + it("select two prime numbers from 1020 to 1050, excluding 1031 and 1049 and combinations", async () => { + const doenetML = ``; + const valid_combinations = [ + [1021, 1039], + [1033, 1021], + [1039, 1033], + ]; + const componentNames = ["/res1", "/res2"]; + + await test_combined_values({ + doenetML, + valid_combinations, + componentNames, + num_samples: 10, + }); + }); + + it("select two prime numbers from 1020 to 1050, excluding 1031 and 1049 and combinations, as copies", async () => { + const doenetML = ` + 1021 1033 + 1033 + 1039 + 1021 + 1021 1033 + 1033 1039 + 1039 1021 + `; + const valid_combinations = [ + [1021, 1039], + [1033, 1021], + [1039, 1033], + ]; + const componentNames = ["/res1", "/res2"]; + + await test_combined_values({ + doenetML, + valid_combinations, + componentNames, + num_samples: 10, + }); + }); + + it("select two prime numbers from 1020 to 1050, excluding 1031 and 1049 and combinations, exclude extras", async () => { + const doenetML = ``; + const valid_combinations = [ + [1021, 1039], + [1033, 1021], + [1039, 1033], + ]; + const componentNames = ["/res1", "/res2"]; + + await test_combined_values({ + doenetML, + valid_combinations, + componentNames, + num_samples: 10, + }); + }); + + it("select three prime numbers up to 5, exclude combinations with two 2s", async () => { + const doenetML = ``; + const valid_combinations = [ + [2, 3, 3], + [2, 3, 5], + [2, 5, 3], + [2, 5, 5], + [3, 2, 3], + [3, 2, 5], + [5, 2, 3], + [5, 2, 5], + [3, 3, 2], + [3, 5, 2], + [5, 3, 2], + [5, 5, 2], + [3, 3, 3], + [3, 3, 5], + [3, 5, 3], + [5, 3, 3], + [5, 5, 3], + [5, 3, 5], + [3, 5, 5], + [5, 5, 5], + ]; + const componentNames = ["/res1", "/res2", "/res3"]; + + await test_combined_values({ + doenetML, + valid_combinations, + componentNames, + num_samples: 10, + }); + }); + + it("select three prime numbers up to 5, exclude combinations with two 2s, duplicate excludes", async () => { + const doenetML = ``; + const valid_combinations = [ + [2, 3, 3], + [2, 3, 5], + [2, 5, 3], + [2, 5, 5], + [3, 2, 3], + [3, 2, 5], + [5, 2, 3], + [5, 2, 5], + [3, 3, 2], + [3, 5, 2], + [5, 3, 2], + [5, 5, 2], + [3, 3, 3], + [3, 3, 5], + [3, 5, 3], + [5, 3, 3], + [5, 5, 3], + [5, 3, 5], + [3, 5, 5], + [5, 5, 5], + ]; + const componentNames = ["/res1", "/res2", "/res3"]; + + await test_combined_values({ + doenetML, + valid_combinations, + componentNames, + num_samples: 10, + }); + }); + + it("select four prime numbers from 3 to 11, exclude positions of each number", async () => { + const doenetML = ``; + const valid_values = [ + [5, 7, 11], + [3, 7, 11], + [3, 5, 11], + [3, 5, 7], + ]; + + const componentNames = ["/res1", "/res2", "/res3", "/res4"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 10, + }); + }); + + it("select three prime numbers up to 5, without replacement exclude positions of each number", async () => { + const doenetML = ``; + const valid_values = [ + [3, 5], + [2, 5], + [2, 3], + ]; + + const componentNames = ["/res1", "/res2", "/res3"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 10, + must_be_distinct: true, + }); + }); + + it("select three prime numbers up to 5, without replacement, exclude any place for 2", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let errorWarnings = core.errorWarnings; + + expect(errorWarnings.errors.length).eq(1); + expect(errorWarnings.warnings.length).eq(0); + + expect(errorWarnings.errors[0].message).contain("Excluded over 70%"); + expect(errorWarnings.errors[0].doenetMLrange.lineBegin).eq(2); + expect(errorWarnings.errors[0].doenetMLrange.charBegin).eq(5); + expect(errorWarnings.errors[0].doenetMLrange.lineEnd).eq(2); + expect(errorWarnings.errors[0].doenetMLrange.charEnd).eq(130); + }); + + it("select 10 prime numbers from the first 10, without replacement, exclude positions of each number", async () => { + // make sure that exclude combinations does not enumerate all combinations excluded + // to count them + const doenetML = ``; + + const allNumbers = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]; + const valid_values: number[][] = []; + + for (let j = 0; j < 10; j++) { + let validNs = [...allNumbers]; + validNs.splice(j, 1); + valid_values.push(validNs); + } + + const componentNames = [ + "/res1", + "/res2", + "/res3", + "/res4", + "/res5", + "/res6", + "/res7", + "/res8", + "/res9", + "/res10", + ]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 5, + must_be_distinct: true, + }); + }); + + it("select five prime numbers with replacement from 1020 to 1050, excluding 1031 and 1049", async () => { + const doenetML = ``; + const valid_values = [ + [1021, 1033, 1039, 1051], + [1021, 1033, 1039, 1051], + [1021, 1033, 1039, 1051], + [1021, 1033, 1039, 1051], + [1021, 1033, 1039, 1051], + ]; + + const componentNames = ["/res1", "/res2", "/res3", "/res4", "/res5"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 5, + }); + }); + + it("select five (number initially unresolved) prime numbers with replacement from 1020 to 1050, excluding 1031 and 1049", async () => { + const doenetML = ` + + $n3{name="n2"} + $num1{name="n"} + $n2+$num2+2 + $n3+$num3 + $num3{name="n3"} + 1`; + + const valid_values = [ + [1021, 1033, 1039, 1051], + [1021, 1033, 1039, 1051], + [1021, 1033, 1039, 1051], + [1021, 1033, 1039, 1051], + [1021, 1033, 1039, 1051], + ]; + + const componentNames = ["/res1", "/res2", "/res3", "/res4", "/res5"]; + + await test_values_separately({ + doenetML, + valid_values, + componentNames, + num_samples: 5, + }); + }); + + it("select 100 large prime numbers, check that are prime", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + for (let ind = 0; ind < 100; ind++) { + let num = + stateVariables[ + stateVariables["/sample"].replacements![ind].componentName + ].stateValues.value; + + expect(Number.isInteger(num) && num >= 2 && num <= 1000000).eq( + true, + ); + + let isPrime = true; + let sqrtNum = Math.sqrt(num); + for (let i = 2; i <= sqrtNum; i++) { + if (num % i === 0) { + isPrime = false; + break; + } + } + expect(isPrime).eq(true); + } + }); + + it("asList", async () => { + let core = await createTestCore({ + doenetML: ` +

+

+ `, + }); + + let results: number[] = []; + + let stateVariables = await returnAllStateVariables(core); + + results.push(stateVariables["/u"].stateValues.value); + results.push(stateVariables["/v"].stateValues.value); + results.push(stateVariables["/w"].stateValues.value); + results.push(stateVariables["/x"].stateValues.value); + results.push(stateVariables["/y"].stateValues.value); + + for (let num of results) { + expect([179, 181, 191, 193, 197, 199].includes(num)); + } + expect(stateVariables["/p1"].stateValues.text).eq(results.join(", ")); + expect(stateVariables["/p2"].stateValues.text).eq(results.join("")); + }); + + it("copies don't resample", async () => { + let core = await createTestCore({ + doenetML: ` +

+ + +

+ +

+ $sample1{name="noresample1"} + $sample2{name="noresample2"} + $noresample1{name="noreresample1"} + $noresample2{name="noreresample2"} +

+ +

+ +

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + let num1 = stateVariables["/n1"].stateValues.value; + let num2 = stateVariables["/n2"].stateValues.value; + expect(Number.isInteger(num1) && num1 >= 2 && num1 <= 100).eq(true); + expect(Number.isInteger(num2) && num2 >= 2 && num2 <= 100).eq(true); + // check numbers are prime + for (let num of [num1, num2]) { + let sqrtNum = Math.sqrt(num); + for (let i = 2; i <= sqrtNum; i++) { + expect(num % i).greaterThan(0); + } + } + + expect( + stateVariables[ + stateVariables["/noresample1"].replacements![0].componentName + ].stateValues.value, + ).eq(num1); + expect( + stateVariables[ + stateVariables["/noresample2"].replacements![0].componentName + ].stateValues.value, + ).eq(num2); + expect( + stateVariables[ + stateVariables["/noreresample1"].replacements![0].componentName + ].stateValues.value, + ).eq(num1); + expect( + stateVariables[ + stateVariables["/noreresample2"].replacements![0].componentName + ].stateValues.value, + ).eq(num2); + + expect( + stateVariables[ + stateVariables["/noresamplep"].activeChildren[1].componentName + ].stateValues.value, + ).eq(num1); + expect( + stateVariables[ + stateVariables["/noresamplep"].activeChildren[3].componentName + ].stateValues.value, + ).eq(num2); + expect( + stateVariables[ + stateVariables["/noreresamplep"].activeChildren[1].componentName + ].stateValues.value, + ).eq(num1); + expect( + stateVariables[ + stateVariables["/noreresamplep"].activeChildren[3].componentName + ].stateValues.value, + ).eq(num2); + }); + + it("select doesn't change dynamically", async () => { + let core = await createTestCore({ + doenetML: ` + + +

+ +

+ + + +

+ +

+

$maxNum2.value{assignNames="maxNum2a"}

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let sample1replacements = stateVariables["/sample1"].replacements!; + let sample2replacements = stateVariables["/sample2"].replacements!; + expect(sample1replacements.length).eq(5); + expect(sample2replacements.length).eq(2); + let sample1numbers = sample1replacements.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let sample2numbers = sample2replacements.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + + for (let num of sample1numbers) { + expect([2, 3].includes(num)).eq(true); + } + for (let num of sample2numbers) { + expect([2, 3, 5, 7].includes(num)).eq(true); + } + + // Nothing changes when change mathInputs + await updateMathInputValue({ + latex: "7", + componentName: "/numToSelect", + core, + }); + await updateMathInputValue({ + latex: "11", + componentName: "/maxNum", + core, + }); + await updateMathInputValue({ + latex: "16", + componentName: "/numToSelect2", + core, + }); + await updateMathInputValue({ + latex: "18", + componentName: "/maxNum2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + sample1replacements = stateVariables["/sample1"].replacements!; + sample2replacements = stateVariables["/sample2"].replacements!; + + expect( + sample1replacements.map( + (x) => stateVariables[x.componentName].stateValues.value, + ), + ).eqls(sample1numbers); + expect( + sample2replacements.map( + (x) => stateVariables[x.componentName].stateValues.value, + ), + ).eqls(sample2numbers); + }); + + it("select doesn't resample in dynamic map", async () => { + let core = await createTestCore({ + doenetML: ` + How many numbers do you want? +

+ + + + +

+ +

$map1

+ + $p1{name="p3"} + $p2{name="p4"} + + $p3{name="p5"} + $p4{name="p6"} + `, + }); + + async function check_sampled_numbers(sampledNumbers: number[]) { + const stateVariables = await returnAllStateVariables(core); + + expect( + stateVariables["/p1"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + + expect( + stateVariables["/p2"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + + expect( + stateVariables["/p3"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + + expect( + stateVariables["/p4"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + + expect( + stateVariables["/p5"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + + expect( + stateVariables["/p6"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + } + + let sampledNumbers: number[] = []; + + // initially nothing + await check_sampled_numbers([]); + + // sample one variable + await updateMathInputValue({ latex: "1", componentName: "/mi1", core }); + + let stateVariables = await returnAllStateVariables(core); + sampledNumbers.push(stateVariables["/a/n"].stateValues.value); + await check_sampled_numbers(sampledNumbers); + + // go back to nothing + await updateMathInputValue({ latex: "0", componentName: "/mi1", core }); + await check_sampled_numbers([]); + + // get same number back + await updateMathInputValue({ latex: "1", componentName: "/mi1", core }); + await check_sampled_numbers(sampledNumbers); + + // get two more samples + await updateMathInputValue({ latex: "3", componentName: "/mi1", core }); + + stateVariables = await returnAllStateVariables(core); + let n1 = stateVariables["/a/n"].stateValues.value; + let n2 = stateVariables["/b/n"].stateValues.value; + let n3 = stateVariables["/c/n"].stateValues.value; + expect(n1).eq(sampledNumbers[0]); + sampledNumbers.push(n2); + sampledNumbers.push(n3); + await check_sampled_numbers(sampledNumbers); + + // go back to nothing + await updateMathInputValue({ latex: "0", componentName: "/mi1", core }); + await check_sampled_numbers([]); + + // get first two numbers back + await updateMathInputValue({ latex: "2", componentName: "/mi1", core }); + await check_sampled_numbers(sampledNumbers.slice(0, 2)); + + // get six total samples + await updateMathInputValue({ latex: "6", componentName: "/mi1", core }); + + stateVariables = await returnAllStateVariables(core); + n1 = stateVariables["/a/n"].stateValues.value; + n2 = stateVariables["/b/n"].stateValues.value; + n3 = stateVariables["/c/n"].stateValues.value; + let n4 = stateVariables["/d/n"].stateValues.value; + let n5 = stateVariables["/e/n"].stateValues.value; + let n6 = stateVariables["/f/n"].stateValues.value; + expect(n1).eq(sampledNumbers[0]); + expect(n2).eq(sampledNumbers[1]); + expect(n3).eq(sampledNumbers[2]); + sampledNumbers.push(n4); + sampledNumbers.push(n5); + sampledNumbers.push(n6); + await check_sampled_numbers(sampledNumbers); + + // go back to nothing + await updateMathInputValue({ latex: "0", componentName: "/mi1", core }); + await check_sampled_numbers([]); + + // get all six back + await updateMathInputValue({ latex: "6", componentName: "/mi1", core }); + await check_sampled_numbers(sampledNumbers); + }); + + it("select prime numbers and sort", async () => { + let core = await createTestCore({ + doenetML: ` +

+ + $p1{name="p2"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let originalNumbers = stateVariables["/p1"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let secondNumbers = stateVariables["/p2"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + + expect([...originalNumbers].sort((a, b) => a - b)).eqls( + originalNumbers, + ); + expect(secondNumbers).eqls(originalNumbers); + }); + + it("select a few prime numbers and sort", async () => { + // Note: checking to make sure unique variants (which could trigger with just 3 numbers) + // doesn't mess this up + // (Currently we have turned off unique variants for sort results + // but this test should still pass if we implement it) + + let core = await createTestCore({ + doenetML: ` +

+ + $p1{name="p2"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let originalNumbers = stateVariables["/p1"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let secondNumbers = stateVariables["/p2"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + + expect([...originalNumbers].sort((a, b) => a - b)).eqls( + originalNumbers, + ); + expect(secondNumbers).eqls(originalNumbers); + }); + + // Note: this test encodes undesired behavior (see issue #246) + // When this issue is resolved, change this test to make sure the references + // are hidden when the selectPrimeNumbers is hidden + it("selectPrimeNumbers hides dynamically", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + +

,

+

$c, $d

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let c = await stateVariables["/c"].stateValues.value; + let d = await stateVariables["/d"].stateValues.value; + expect([2, 3, 5, 7].includes(c)).eq(true); + expect([2, 3, 5, 7].includes(d)).eq(true); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq(`${c}, `); + expect(stateVariables["/p2"].stateValues.text).eq(`${c}, ${d}`); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/h1", + core, + }); + await updateBooleanInputValue({ + boolean: false, + componentName: "/h2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq(`, ${d}`); + expect(stateVariables["/p2"].stateValues.text).eq(`${c}, ${d}`); + + await updateBooleanInputValue({ + boolean: false, + componentName: "/h1", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/h2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq(`${c}, `); + expect(stateVariables["/p2"].stateValues.text).eq(`${c}, ${d}`); + }); + + it("numToSelect from selectFromSequence", async () => { + let core = await createTestCore({ + doenetML: ` +

n1 =

+

nums =

+

a1=$a1, b1=$b1, c1=$c1, d1=$d1, e1=$e1

+ +

n2 =

+

nums =

+

a2=$a2, b2=$b2, c2=$c2, d2=$d2, e2=$e2

+ +

n3 =

+

nums =

+

a3=$a3, b3=$b3, c3=$c3, d3=$d3, e3=$e3

+ +

n4 =

+

nums =

+

a4=$a4, b4=$b4, c4=$c4, d4=$d4, e4=$e4

+ +

n5 =

+

nums =

+

a5=$a5, b5=$b5, c5=$c5, d5=$d5, e5=$e5

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let n1 = stateVariables["/n1"].stateValues.value; + let n2 = stateVariables["/n2"].stateValues.value; + let n3 = stateVariables["/n3"].stateValues.value; + let n4 = stateVariables["/n4"].stateValues.value; + let n5 = stateVariables["/n5"].stateValues.value; + + let nums1 = stateVariables["/nums1"].replacements!.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let nums2 = stateVariables["/nums2"].replacements!.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let nums3 = stateVariables["/nums3"].replacements!.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let nums4 = stateVariables["/nums4"].replacements!.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let nums5 = stateVariables["/nums5"].replacements!.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + + expect(nums1.length).eq(n1); + expect(nums2.length).eq(n2); + expect(nums3.length).eq(n3); + expect(nums4.length).eq(n4); + expect(nums5.length).eq(n5); + + nums1.length = 5; + nums2.length = 5; + nums3.length = 5; + nums4.length = 5; + nums5.length = 5; + + nums1.fill("", n1); + nums2.fill("", n2); + nums3.fill("", n3); + nums4.fill("", n4); + nums5.fill("", n5); + + let l = ["a", "b", "c", "d", "e"]; + + expect(stateVariables["/p1"].stateValues.text).eq( + nums1.map((v, i) => `${l[i]}1=${v}`).join(", "), + ); + expect(stateVariables["/p2"].stateValues.text).eq( + nums2.map((v, i) => `${l[i]}2=${v}`).join(", "), + ); + expect(stateVariables["/p3"].stateValues.text).eq( + nums3.map((v, i) => `${l[i]}3=${v}`).join(", "), + ); + expect(stateVariables["/p4"].stateValues.text).eq( + nums4.map((v, i) => `${l[i]}4=${v}`).join(", "), + ); + expect(stateVariables["/p5"].stateValues.text).eq( + nums5.map((v, i) => `${l[i]}5=${v}`).join(", "), + ); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/selectsamplerandomnumbers.test.ts b/packages/doenetml-worker/src/test/tagSpecific/selectsamplerandomnumbers.test.ts new file mode 100644 index 000000000..7d612f52d --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/selectsamplerandomnumbers.test.ts @@ -0,0 +1,1895 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { updateMathInputValue, updateTextInputValue } from "../utils/actions"; +import me from "math-expressions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +describe("SelectRandomNumbers and SampleRandomNumbers tag tests", async () => { + async function test_combined_statistics({ + doenetML, + componentName, + numSamplesPerComponent, + numRepetitions, + minValue, + strictMin = true, + maxValue, + strictMax = true, + validValues, + allowedMeanMid, + allowedMeanSpread, + allowedVarianceMid, + allowedVarianceSpread, + expectedMean, + expectedVariance, + }: { + doenetML: string; + componentName: string; + numSamplesPerComponent: number; + numRepetitions: number; + minValue?: number; + strictMin?: boolean; + maxValue?: number; + strictMax?: boolean; + validValues?: number[]; + allowedMeanMid?: number; + allowedMeanSpread?: number; + allowedVarianceMid?: number; + allowedVarianceSpread?: number; + expectedMean?: number; + expectedVariance?: number; + }) { + let samples: number[] = []; + for (let i = 0; i < numRepetitions; i++) { + let core = await createTestCore({ + doenetML, + requestedVariantIndex: i, + }); + const stateVariables = await returnAllStateVariables(core); + samples.push( + ...stateVariables[componentName].replacements!.map( + (x) => stateVariables[x.componentName].stateValues.value, + ), + ); + + if (expectedMean !== undefined && i == 0) { + expect(stateVariables[componentName].stateValues.mean).closeTo( + expectedMean, + 1e-10, + ); + } + + if (expectedVariance !== undefined && i == 0) { + expect( + stateVariables[componentName].stateValues.variance, + ).closeTo(expectedVariance, 1e-10); + expect( + stateVariables[componentName].stateValues.standardDeviation, + ).closeTo(Math.sqrt(expectedVariance), 1e-10); + } + } + + expect(samples.length).eq(numSamplesPerComponent * numRepetitions); + + if (minValue !== undefined) { + for (let sample of samples) { + if (strictMin) { + expect(sample).gt(minValue); + } else { + expect(sample).gte(minValue); + } + } + } + + if (maxValue !== undefined) { + for (let sample of samples) { + if (strictMax) { + expect(sample).lt(maxValue); + } else { + expect(sample).lte(maxValue); + } + } + } + + if (validValues !== undefined) { + for (let sample of samples) { + expect(validValues.includes(sample)).eq(true); + } + } + + if (allowedMeanMid !== undefined && allowedMeanSpread !== undefined) { + let meanX = me.math.mean(samples); + expect(meanX).closeTo(allowedMeanMid, allowedMeanSpread); + } + + if ( + allowedVarianceMid !== undefined && + allowedVarianceSpread !== undefined + ) { + let varX = me.math.variance(samples, "uncorrected"); + expect(varX).closeTo(allowedVarianceMid, allowedVarianceSpread); + } + } + + it("no parameters, single uniform random number from 0 to 1", async () => { + const doenetMLs = [ + ``, + ``, + ]; + + for (let doenetML of doenetMLs) { + await test_combined_statistics({ + doenetML, + componentName: "/s", + numSamplesPerComponent: 1, + numRepetitions: 400, + minValue: 0, + strictMin: true, + maxValue: 1, + strictMax: false, + allowedMeanMid: 0.5, + allowedMeanSpread: 0.05, + allowedVarianceMid: 1 / 12, + allowedVarianceSpread: 0.015, + expectedMean: 0.5, + expectedVariance: 1 / 12, + }); + } + }); + + it("five uniform random numbers from 0 to 8, only to specified", async () => { + const doenetMLs = [ + ``, + ``, + ]; + + for (let doenetML of doenetMLs) { + await test_combined_statistics({ + doenetML, + componentName: "/s", + numSamplesPerComponent: 5, + numRepetitions: 80, + minValue: 0, + strictMin: true, + maxValue: 8, + strictMax: false, + allowedMeanMid: 4, + allowedMeanSpread: 0.5, + allowedVarianceMid: 8 ** 2 / 12, + allowedVarianceSpread: 0.8, + expectedMean: 4, + expectedVariance: 8 ** 2 / 12, + }); + } + }); + + it("five uniform random numbers from -5 to -4, only from specified", async () => { + const doenetMLs = [ + ``, + ``, + ]; + + for (let doenetML of doenetMLs) { + await test_combined_statistics({ + doenetML, + componentName: "/s", + numSamplesPerComponent: 5, + numRepetitions: 80, + minValue: -5, + strictMin: true, + maxValue: -4, + strictMax: false, + allowedMeanMid: -4.5, + allowedMeanSpread: 0.05, + allowedVarianceMid: 1 / 12, + allowedVarianceSpread: 0.015, + expectedMean: -4.5, + expectedVariance: 1 / 12, + }); + } + }); + + it("select ten uniform random numbers from -4 to -2", async () => { + const doenetMLs = [ + ``, + ``, + ]; + + for (let doenetML of doenetMLs) { + await test_combined_statistics({ + doenetML, + componentName: "/s", + numSamplesPerComponent: 10, + numRepetitions: 40, + minValue: -4, + strictMin: true, + maxValue: -2, + strictMax: false, + allowedMeanMid: -3, + allowedMeanSpread: 0.5, + allowedVarianceMid: 2 ** 2 / 12, + allowedVarianceSpread: 0.5, + expectedMean: -3, + expectedVariance: 2 ** 2 / 12, + }); + } + }); + + it("ten uniform random numbers from -2 to -4", async () => { + const doenetMLs = [ + ``, + ``, + ]; + + for (let doenetML of doenetMLs) { + await test_combined_statistics({ + doenetML, + componentName: "/s", + numSamplesPerComponent: 10, + numRepetitions: 10, + minValue: -4, + strictMin: true, + maxValue: -2, + strictMax: false, + allowedMeanMid: -3, + allowedMeanSpread: 0.5, + allowedVarianceMid: 2 ** 2 / 12, + allowedVarianceSpread: 0.5, + expectedMean: -3, + expectedVariance: 2 ** 2 / 12, + }); + } + }); + + it("twenty continuous standard normals, no parameters", async () => { + const doenetMLs = [ + ``, + ``, + ]; + + for (let doenetML of doenetMLs) { + await test_combined_statistics({ + doenetML, + componentName: "/s", + numSamplesPerComponent: 20, + numRepetitions: 20, + allowedMeanMid: 0, + allowedMeanSpread: 0.2, + allowedVarianceMid: 1, + allowedVarianceSpread: 0.3, + expectedMean: 0, + expectedVariance: 1, + }); + } + }); + + it("five continuous standard normals, unspecified mean 0, standard deviation 10", async () => { + const doenetMLs = [ + ``, + ``, + ]; + + for (let doenetML of doenetMLs) { + await test_combined_statistics({ + doenetML, + componentName: "/s", + numSamplesPerComponent: 5, + numRepetitions: 80, + allowedMeanMid: 0, + allowedMeanSpread: 2, + allowedVarianceMid: 100, + allowedVarianceSpread: 25, + expectedMean: 0, + expectedVariance: 100, + }); + } + }); + + it("single continuous standard normal, mean -50, unspecified standard deviation 1", async () => { + const doenetMLs = [ + ``, + ``, + ]; + + for (let doenetML of doenetMLs) { + await test_combined_statistics({ + doenetML, + componentName: "/s", + numSamplesPerComponent: 1, + numRepetitions: 400, + allowedMeanMid: -50, + allowedMeanSpread: 0.2, + allowedVarianceMid: 1, + allowedVarianceSpread: 0.3, + expectedMean: -50, + expectedVariance: 1, + }); + } + }); + + it("twenty continuous standard normals, mean -3, variance 0.01", async () => { + const doenetMLs = [ + ``, + ``, + ]; + + for (let doenetML of doenetMLs) { + await test_combined_statistics({ + doenetML, + componentName: "/s", + numSamplesPerComponent: 20, + numRepetitions: 5, + allowedMeanMid: -3, + allowedMeanSpread: 0.1, + allowedVarianceMid: 0.01, + allowedVarianceSpread: 0.004, + expectedMean: -3, + expectedVariance: 0.01, + }); + } + }); + + it("single discrete uniform, no parameters, integer from 0 to 1", async () => { + const doenetMLs = [ + ``, + ``, + ]; + + for (let doenetML of doenetMLs) { + await test_combined_statistics({ + doenetML, + componentName: "/s", + numSamplesPerComponent: 1, + numRepetitions: 400, + validValues: [0, 1], + allowedMeanMid: 0.5, + allowedMeanSpread: 0.1, + allowedVarianceMid: (2 ** 2 - 1) / 12, + allowedVarianceSpread: 0.1, + expectedMean: 0.5, + expectedVariance: (2 ** 2 - 1) / 12, + }); + } + }); + + it("single discrete uniform, from 0.5 to 5.5, only to specified", async () => { + const doenetMLs = [ + ``, + ``, + ]; + + for (let doenetML of doenetMLs) { + await test_combined_statistics({ + doenetML, + componentName: "/s", + numSamplesPerComponent: 1, + numRepetitions: 400, + validValues: [0.5, 1.5, 2.5, 3.5, 4.5, 5.5], + allowedMeanMid: 3, + allowedMeanSpread: 0.3, + allowedVarianceMid: (6 ** 2 - 1) / 12, + allowedVarianceSpread: 0.5, + expectedMean: 3, + expectedVariance: (6 ** 2 - 1) / 12, + }); + } + }); + + it("single discrete uniform, from 8.5 to 9.5, only from specified", async () => { + const doenetMLs = [ + ``, + ``, + ]; + + for (let doenetML of doenetMLs) { + await test_combined_statistics({ + doenetML, + componentName: "/s", + numSamplesPerComponent: 1, + numRepetitions: 400, + validValues: [8.5, 9.5], + allowedMeanMid: 9, + allowedMeanSpread: 0.1, + allowedVarianceMid: (2 ** 2 - 1) / 12, + allowedVarianceSpread: 0.05, + expectedMean: 9, + expectedVariance: (2 ** 2 - 1) / 12, + }); + } + }); + + it("five integers from -3 to 5", async () => { + const doenetMLs = [ + ``, + ``, + ]; + + for (let doenetML of doenetMLs) { + await test_combined_statistics({ + doenetML, + componentName: "/s", + numSamplesPerComponent: 5, + numRepetitions: 80, + validValues: [-3, -2, -1, 0, 1, 2, 3, 4, 5], + allowedMeanMid: 1, + allowedMeanSpread: 0.5, + allowedVarianceMid: (9 ** 2 - 1) / 12, + allowedVarianceSpread: 1, + expectedMean: 1, + expectedVariance: (9 ** 2 - 1) / 12, + }); + } + }); + + it("five integers from 5 to -3 gives nothing", async () => { + const doenetMLs = [ + ``, + ``, + ]; + + for (let doenetML of doenetMLs) { + await test_combined_statistics({ + doenetML, + componentName: "/s", + numSamplesPerComponent: 0, + numRepetitions: 20, + }); + } + }); + + it("10 odd integers from -3 to 5", async () => { + const doenetMLs = [ + ``, + ``, + ]; + + for (let doenetML of doenetMLs) { + await test_combined_statistics({ + doenetML, + componentName: "/s", + numSamplesPerComponent: 10, + numRepetitions: 40, + validValues: [-3, -1, 1, 3, 5], + allowedMeanMid: 1, + allowedMeanSpread: 0.5, + allowedVarianceMid: ((5 ** 2 - 1) * 2 ** 2) / 12, + allowedVarianceSpread: 1, + expectedMean: 1, + expectedVariance: ((5 ** 2 - 1) * 2 ** 2) / 12, + }); + } + }); + + it("single discrete uniform, no parameters except exclude, get first two non-negative integers", async () => { + const doenetMLs = [ + ``, + ``, + ]; + + for (let doenetML of doenetMLs) { + await test_combined_statistics({ + doenetML, + componentName: "/s", + numSamplesPerComponent: 1, + numRepetitions: 400, + validValues: [1, 3], + allowedMeanMid: 2, + allowedMeanSpread: 0.2, + allowedVarianceMid: ((2 ** 2 - 1) * 2 ** 2) / 12, + allowedVarianceSpread: 0.2, + expectedMean: 2, + expectedVariance: ((2 ** 2 - 1) * 2 ** 2) / 12, + }); + } + }); + + it("single discrete uniform, from 0.5 to 4.5, exclude 1.5, 3.5, only to and exclude specified", async () => { + const doenetMLs = [ + ``, + ``, + ]; + + for (let doenetML of doenetMLs) { + await test_combined_statistics({ + doenetML, + componentName: "/s", + numSamplesPerComponent: 1, + numRepetitions: 400, + validValues: [0.5, 2.5, 4.5], + allowedMeanMid: 2.5, + allowedMeanSpread: 0.3, + allowedVarianceMid: ((3 ** 2 - 1) * 2 ** 2) / 12, + allowedVarianceSpread: 0.5, + expectedMean: 2.5, + expectedVariance: ((3 ** 2 - 1) * 2 ** 2) / 12, + }); + } + }); + + it("single discrete uniform, from 6.5 to 9.5 exclude 6.5, 8.6, only from and exclude specified", async () => { + const doenetMLs = [ + ``, + ``, + ]; + + for (let doenetML of doenetMLs) { + await test_combined_statistics({ + doenetML, + componentName: "/s", + numSamplesPerComponent: 1, + numRepetitions: 400, + validValues: [7.5, 9.5], + allowedMeanMid: 8.5, + allowedMeanSpread: 0.2, + allowedVarianceMid: ((2 ** 2 - 1) * 2 ** 2) / 12, + allowedVarianceSpread: 0.5, + expectedMean: 8.5, + expectedVariance: ((2 ** 2 - 1) * 2 ** 2) / 12, + }); + } + }); + + it("five integers from -3 to 5, excluding -2 and 0", async () => { + const doenetMLs = [ + ``, + ``, + ]; + + let vals = [-3, -1, 1, 2, 3, 4, 5]; + let mean = me.math.mean(vals); + let variance = me.math.variance(vals, "uncorrected"); + + for (let doenetML of doenetMLs) { + await test_combined_statistics({ + doenetML, + componentName: "/s", + numSamplesPerComponent: 5, + numRepetitions: 80, + validValues: vals, + allowedMeanMid: mean, + allowedMeanSpread: 0.5, + allowedVarianceMid: variance, + allowedVarianceSpread: 1, + expectedMean: mean, + expectedVariance: variance, + }); + } + }); + + it("10 odd integers from -3 to 5, excluding 3", async () => { + const doenetMLs = [ + ``, + ``, + ]; + + let vals = [-3, -1, 1, 5]; + let mean = me.math.mean(vals); + let variance = me.math.variance(vals, "uncorrected"); + + for (let doenetML of doenetMLs) { + await test_combined_statistics({ + doenetML, + componentName: "/s", + numSamplesPerComponent: 10, + numRepetitions: 40, + validValues: vals, + allowedMeanMid: mean, + allowedMeanSpread: 0.5, + allowedVarianceMid: variance, + allowedVarianceSpread: 1, + expectedMean: mean, + expectedVariance: variance, + }); + } + }); + + it("asList", async () => { + let core = await createTestCore({ + doenetML: ` +

+

+

+

+ `, + }); + + let results: number[] = []; + let results2: number[] = []; + + let stateVariables = await returnAllStateVariables(core); + + results.push(stateVariables["/u"].stateValues.value); + results.push(stateVariables["/v"].stateValues.value); + results.push(stateVariables["/w"].stateValues.value); + results.push(stateVariables["/x"].stateValues.value); + results.push(stateVariables["/y"].stateValues.value); + results2.push(stateVariables["/u2"].stateValues.value); + results2.push(stateVariables["/v2"].stateValues.value); + results2.push(stateVariables["/w2"].stateValues.value); + results2.push(stateVariables["/x2"].stateValues.value); + results2.push(stateVariables["/y2"].stateValues.value); + + for (let num of results) { + expect(num).gte(175).lte(205); + } + for (let num of results2) { + expect(num).gte(175).lte(205); + } + + let roundedResults = results.map((x) => Math.round(x * 100) / 100); + expect(stateVariables["/p1"].stateValues.text).eq( + roundedResults.join(", "), + ); + expect(stateVariables["/p2"].stateValues.text).eq( + roundedResults.join(""), + ); + let roundedResults2 = results2.map((x) => Math.round(x * 100) / 100); + expect(stateVariables["/p3"].stateValues.text).eq( + roundedResults2.join(", "), + ); + expect(stateVariables["/p4"].stateValues.text).eq( + roundedResults2.join(""), + ); + }); + + it("select doesn't change dynamically", async () => { + let core = await createTestCore({ + doenetML: ` + + +

+ +

+ + + +

+ +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let sample1replacements = stateVariables["/sample1"].replacements!; + let sample2replacements = stateVariables["/sample2"].replacements!; + expect(sample1replacements.length).eq(20); + expect(sample2replacements.length).eq(10); + let sample1numbers = sample1replacements.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let sample2numbers = sample2replacements.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + + for (let num of sample1numbers) { + expect(num).gte(0); + expect(num).lt(10); + } + for (let num of sample2numbers) { + expect([0, 1, 2, 3, 4].includes(num)).eq(true); + } + + // Nothing changes when change mathInputs + await updateMathInputValue({ + latex: "7", + componentName: "/numToSelect", + core, + }); + await updateMathInputValue({ + latex: "11", + componentName: "/maxNum", + core, + }); + await updateMathInputValue({ + latex: "16", + componentName: "/numToSelect2", + core, + }); + await updateMathInputValue({ + latex: "18", + componentName: "/maxNum2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + sample1replacements = stateVariables["/sample1"].replacements!; + sample2replacements = stateVariables["/sample2"].replacements!; + + expect( + sample1replacements.map( + (x) => stateVariables[x.componentName].stateValues.value, + ), + ).eqls(sample1numbers); + expect( + sample2replacements.map( + (x) => stateVariables[x.componentName].stateValues.value, + ), + ).eqls(sample2numbers); + }); + + it("sampled number does change dynamically", async () => { + let core = await createTestCore({ + doenetML: ` + + +

+ +

+ + + +

+ +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let sample1replacements = stateVariables["/sample1"].replacements!; + let sample2replacements = stateVariables["/sample2"].replacements!; + expect(sample1replacements.length).eq(50); + expect(sample2replacements.length).eq(180); + let sample1numbers = sample1replacements.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let sample2numbers = sample2replacements.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + + for (let num of sample1numbers) { + expect(num).gte(0); + expect(num).lt(10); + } + + expect(me.math.mean(sample1numbers)).closeTo(5, 2); + expect(me.math.variance(sample1numbers, "uncorrected")).closeTo( + 10 ** 2 / 12, + 3, + ); + + expect(me.math.mean(sample2numbers)).closeTo(0, 1.5); + expect(me.math.variance(sample2numbers, "uncorrected")).closeTo(16, 8); + + // Get new samples when change number of samples + await updateMathInputValue({ + latex: "70", + componentName: "/numSamples", + core, + }); + await updateMathInputValue({ + latex: "160", + componentName: "/numSamples2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + let sample1numbersb = stateVariables["/sample1"].replacements!.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let sample2numbersb = stateVariables["/sample2"] + .replacements!.slice( + 0, + stateVariables["/sample2"].replacements!.length - + (stateVariables["/sample2"].replacementsToWithhold ?? 0), + ) + .map((x) => stateVariables[x.componentName].stateValues.value); + expect(sample1numbersb.length).eq(70); + expect(sample2numbersb.length).eq(160); + + for (let num of sample1numbersb) { + expect(num).gte(0); + expect(num).lt(10); + } + + expect(me.math.mean(sample1numbersb)).closeTo(5, 2); + expect(me.math.variance(sample1numbersb, "uncorrected")).closeTo( + 10 ** 2 / 12, + 4, + ); + + expect(me.math.mean(sample2numbersb)).closeTo(0, 1.5); + expect(me.math.variance(sample2numbersb, "uncorrected")).closeTo(16, 8); + + for (let ind = 0; ind < 10; ind++) { + expect(sample1numbersb[ind]).not.eq(sample1numbers[ind]); + } + for (let ind = 0; ind < 10; ind++) { + expect(sample2numbersb[ind]).not.eq(sample2numbers[ind]); + } + + // Get new samples when sample parameters + await updateMathInputValue({ + latex: "4", + componentName: "/maxNum", + core, + }); + await updateMathInputValue({ + latex: "18", + componentName: "/standardDeviation", + core, + }); + + stateVariables = await returnAllStateVariables(core); + let sample1numbersc = stateVariables["/sample1"].replacements!.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let sample2numbersc = stateVariables["/sample2"] + .replacements!.slice( + 0, + stateVariables["/sample2"].replacements!.length - + (stateVariables["/sample2"].replacementsToWithhold ?? 0), + ) + .map((x) => stateVariables[x.componentName].stateValues.value); + expect(sample1numbersc.length).eq(70); + expect(sample2numbersc.length).eq(160); + + for (let num of sample1numbersc) { + expect(num).gte(0); + expect(num).lt(4); + } + expect(me.math.mean(sample1numbersc)).closeTo(2, 1); + expect(me.math.variance(sample1numbersc, "uncorrected")).closeTo( + 4 ** 2 / 12, + 1, + ); + + expect(me.math.mean(sample2numbersc)).closeTo(0, 6); + expect(me.math.variance(sample2numbersc, "uncorrected")).closeTo( + 18 ** 2, + 120, + ); + + for (let ind = 0; ind < 10; ind++) { + expect(sample1numbersc[ind]).not.eq(sample1numbersb[ind]); + } + for (let ind = 0; ind < 10; ind++) { + expect(sample2numbersc[ind]).not.eq(sample2numbersb[ind]); + } + }); + + async function test_no_resample(core) { + async function check_sampled_numbers(sampledNumbers: number[]) { + const stateVariables = await returnAllStateVariables(core); + + expect( + stateVariables["/p1"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + + expect( + stateVariables["/p2"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + + expect( + stateVariables["/p3"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + + expect( + stateVariables["/p4"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + + expect( + stateVariables["/p5"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + + expect( + stateVariables["/p6"].activeChildren.map( + (child) => + stateVariables[child.componentName].stateValues.value, + ), + ).eqls(sampledNumbers); + } + + let sampledNumbers: number[] = []; + + // initially nothing + await check_sampled_numbers([]); + + // sample one variable + await updateMathInputValue({ latex: "1", componentName: "/mi1", core }); + + let stateVariables = await returnAllStateVariables(core); + sampledNumbers.push(stateVariables["/a/n"].stateValues.value); + await check_sampled_numbers(sampledNumbers); + + // go back to nothing + await updateMathInputValue({ latex: "0", componentName: "/mi1", core }); + await check_sampled_numbers([]); + + // get same number back + await updateMathInputValue({ latex: "1", componentName: "/mi1", core }); + await check_sampled_numbers(sampledNumbers); + + // get two more samples + await updateMathInputValue({ latex: "3", componentName: "/mi1", core }); + + stateVariables = await returnAllStateVariables(core); + let n1 = stateVariables["/a/n"].stateValues.value; + let n2 = stateVariables["/b/n"].stateValues.value; + let n3 = stateVariables["/c/n"].stateValues.value; + expect(n1).eq(sampledNumbers[0]); + sampledNumbers.push(n2); + sampledNumbers.push(n3); + await check_sampled_numbers(sampledNumbers); + + // go back to nothing + await updateMathInputValue({ latex: "0", componentName: "/mi1", core }); + await check_sampled_numbers([]); + + // get first two numbers back + await updateMathInputValue({ latex: "2", componentName: "/mi1", core }); + await check_sampled_numbers(sampledNumbers.slice(0, 2)); + + // get six total samples + await updateMathInputValue({ latex: "6", componentName: "/mi1", core }); + + stateVariables = await returnAllStateVariables(core); + n1 = stateVariables["/a/n"].stateValues.value; + n2 = stateVariables["/b/n"].stateValues.value; + n3 = stateVariables["/c/n"].stateValues.value; + let n4 = stateVariables["/d/n"].stateValues.value; + let n5 = stateVariables["/e/n"].stateValues.value; + let n6 = stateVariables["/f/n"].stateValues.value; + expect(n1).eq(sampledNumbers[0]); + expect(n2).eq(sampledNumbers[1]); + expect(n3).eq(sampledNumbers[2]); + sampledNumbers.push(n4); + sampledNumbers.push(n5); + sampledNumbers.push(n6); + await check_sampled_numbers(sampledNumbers); + + // go back to nothing + await updateMathInputValue({ latex: "0", componentName: "/mi1", core }); + await check_sampled_numbers([]); + + // get all six back + await updateMathInputValue({ latex: "6", componentName: "/mi1", core }); + await check_sampled_numbers(sampledNumbers); + } + + it("select doesn't resample in dynamic map", async () => { + let core = await createTestCore({ + doenetML: ` + How many numbers do you want? +

+ + + + +

+ +

$map1

+ + $p1{name="p3"} + $p2{name="p4"} + + $p3{name="p5"} + $p4{name="p6"} + `, + }); + + await test_no_resample(core); + }); + + it("random number doesn't resample in dynamic map", async () => { + let core = await createTestCore({ + doenetML: ` + How many numbers do you want? +

+ + + + +

+ +

$map1

+ + $p1{name="p3"} + $p2{name="p4"} + + $p3{name="p5"} + $p4{name="p6"} + `, + }); + + await test_no_resample(core); + }); + + it("single discrete uniform number, assign name", async () => { + const doenetMLs = [ + `

+

+

+

$u{name="u2"}

+

$v{name="v2"}

+

$w{name="w2"}

+ `, + `

+

+

+

$u{name="u2"}

+

$v{name="v2"}

+

$w{name="w2"}

`, + ]; + + for (let doenetML of doenetMLs) { + let core = await createTestCore({ doenetML }); + + let options = [3, 10]; + + let stateVariables = await returnAllStateVariables(core); + + let u = stateVariables["/u"]; + let u2 = stateVariables["/u2"]; + + expect(options.includes(u.stateValues.value)).eq(true); + expect(u.stateValues.value).eq(u2.stateValues.value); + + let v = stateVariables["/v"]; + let v2 = stateVariables["/v2"]; + expect(options.includes(v.stateValues.value)).eq(true); + expect(v.stateValues.value).eq(v2.stateValues.value); + + let w = stateVariables["/w"]; + let w2 = stateVariables["/w2"]; + expect(options.includes(w.stateValues.value)).eq(true); + expect(w.stateValues.value).eq(w2.stateValues.value); + } + }); + + it("multiple uniform random numbers, assign names", async () => { + const doenetMLs = [ + ` +

+ +

+

$u{name="u2"}

+

$v{name="v2"}

+

$w{name="w2"}

+ `, + ` +

+ +

+

$u{name="u2"}

+

$v{name="v2"}

+

$w{name="w2"}

+ `, + ]; + + for (let doenetML of doenetMLs) { + let core = await createTestCore({ doenetML }); + + let results: number[] = []; + + let stateVariables = await returnAllStateVariables(core); + let s = stateVariables["/s"]; + expect(s.replacements!.length).eq(6); + for (let ind = 0; ind < 6; ind++) { + let num = + stateVariables[s.replacements![ind].componentName] + .stateValues.value; + results[ind] = num; + expect(num).gte(3); + expect(num).lt(13); + } + + let u = stateVariables["/u"]; + let u2 = stateVariables["/u2"]; + expect(u.stateValues.value).eq(results[0]); + expect(u2.stateValues.value).eq(results[0]); + + let v = stateVariables["/v"]; + let v2 = stateVariables["/v2"]; + expect(v.stateValues.value).eq(results[1]); + expect(v2.stateValues.value).eq(results[1]); + + let w = stateVariables["/w"]; + let w2 = stateVariables["/w2"]; + expect(w.stateValues.value).eq(results[2]); + expect(w2.stateValues.value).eq(results[2]); + } + }); + + it("multiple uniform random numbers, assign names, newNamespace", async () => { + const doenetMLs = [ + ` +

+ +

+

$(s/u{name="u2"})

+

$(s/v{name="v2"})

+

$(s/w{name="w2"})

+ `, + ` +

+ +

+

$(s/u{name="u2"})

+

$(s/v{name="v2"})

+

$(s/w{name="w2"})

+ `, + ]; + + for (let doenetML of doenetMLs) { + let core = await createTestCore({ doenetML }); + + let results: number[] = []; + + let stateVariables = await returnAllStateVariables(core); + let s = stateVariables["/s"]; + expect(s.replacements!.length).eq(6); + for (let ind = 0; ind < 6; ind++) { + let num = + stateVariables[s.replacements![ind].componentName] + .stateValues.value; + results[ind] = num; + expect(num).gte(3); + expect(num).lt(13); + } + + let u = stateVariables["/s/u"]; + let u2 = stateVariables["/u2"]; + expect(u.stateValues.value).eq(results[0]); + expect(u2.stateValues.value).eq(results[0]); + + let v = stateVariables["/s/v"]; + let v2 = stateVariables["/v2"]; + expect(v.stateValues.value).eq(results[1]); + expect(v2.stateValues.value).eq(results[1]); + + let w = stateVariables["/s/w"]; + let w2 = stateVariables["/w2"]; + expect(w.stateValues.value).eq(results[2]); + expect(w2.stateValues.value).eq(results[2]); + } + }); + + it("numToSelect from selectFromSequence", async () => { + let core = await createTestCore({ + doenetML: ` +

n1 =

+

nums =

+

a1=$a1, b1=$b1, c1=$c1, d1=$d1, e1=$e1

+ +

n2 =

+

nums =

+

a2=$a2, b2=$b2, c2=$c2, d2=$d2, e2=$e2

+ +

n3 =

+

nums =

+

a3=$a3, b3=$b3, c3=$c3, d3=$d3, e3=$e3

+ +

n4 =

+

nums =

+

a4=$a4, b4=$b4, c4=$c4, d4=$d4, e4=$e4

+ +

n5 =

+

nums =

+

a5=$a5, b5=$b5, c5=$c5, d5=$d5, e5=$e5

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let n1 = stateVariables["/n1"].stateValues.value; + let n2 = stateVariables["/n2"].stateValues.value; + let n3 = stateVariables["/n3"].stateValues.value; + let n4 = stateVariables["/n4"].stateValues.value; + let n5 = stateVariables["/n5"].stateValues.value; + + let nums1 = stateVariables["/nums1"].replacements!.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let nums2 = stateVariables["/nums2"].replacements!.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let nums3 = stateVariables["/nums3"].replacements!.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let nums4 = stateVariables["/nums4"].replacements!.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + let nums5 = stateVariables["/nums5"].replacements!.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + + expect(nums1.length).eq(n1); + expect(nums2.length).eq(n2); + expect(nums3.length).eq(n3); + expect(nums4.length).eq(n4); + expect(nums5.length).eq(n5); + + nums1.length = 5; + nums2.length = 5; + nums3.length = 5; + nums4.length = 5; + nums5.length = 5; + + nums1.fill("", n1); + nums2.fill("", n2); + nums3.fill("", n3); + nums4.fill("", n4); + nums5.fill("", n5); + + let l = ["a", "b", "c", "d", "e"]; + + expect(stateVariables["/p1"].stateValues.text).eq( + nums1 + .map((v, i) => `${l[i]}1=${v ? Math.round(v * 1e9) / 1e9 : ""}`) + .join(", "), + ); + expect(stateVariables["/p2"].stateValues.text).eq( + nums2 + .map((v, i) => `${l[i]}2=${v ? Math.round(v * 1e9) / 1e9 : ""}`) + .join(", "), + ); + expect(stateVariables["/p3"].stateValues.text).eq( + nums3 + .map((v, i) => `${l[i]}3=${v ? Math.round(v * 1e9) / 1e9 : ""}`) + .join(", "), + ); + expect(stateVariables["/p4"].stateValues.text).eq( + nums4 + .map((v, i) => `${l[i]}4=${v ? Math.round(v * 1e9) / 1e9 : ""}`) + .join(", "), + ); + expect(stateVariables["/p5"].stateValues.text).eq( + nums5 + .map((v, i) => `${l[i]}5=${v ? Math.round(v * 1e9) / 1e9 : ""}`) + .join(", "), + ); + }); + + it("rounding", async () => { + let core = await createTestCore({ + doenetML: ` +

+

+

+

+ +

+

+

+

+ +

$n1

+

$n2

+

$n3

+

$n4

+ +

$n5

+

$n6

+

$n7

+

$n8

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + let n1 = stateVariables["/n1"].stateValues.value; + let n2 = stateVariables["/n2"].stateValues.value; + let n3 = stateVariables["/n3"].stateValues.value; + let n4 = stateVariables["/n4"].stateValues.value; + let n5 = stateVariables["/n5"].stateValues.value; + let n6 = stateVariables["/n6"].stateValues.value; + let n7 = stateVariables["/n7"].stateValues.value; + let n8 = stateVariables["/n8"].stateValues.value; + + expect(stateVariables["/n1"].stateValues.text).eq( + String(Math.round(n1 * 10 ** 8) / 10 ** 8), + ); + expect(stateVariables["/n2"].stateValues.text).eq( + String(Math.round(n2 * 10 ** 1) / 10 ** 1), + ); + expect(stateVariables["/n3"].stateValues.text).eq( + String(Math.round(n3 * 10 ** 3) / 10 ** 3), + ); + expect(stateVariables["/n4"].stateValues.text).eq(String(n4) + ".0"); + expect(stateVariables["/n5"].stateValues.text).eq( + String(Math.round(n5 * 10 ** 8) / 10 ** 8), + ); + expect(stateVariables["/n6"].stateValues.text).eq( + String(Math.round(n6 * 10 ** 1) / 10 ** 1), + ); + expect(stateVariables["/n7"].stateValues.text).eq( + String(Math.round(n7 * 10 ** 3) / 10 ** 3), + ); + expect(stateVariables["/n8"].stateValues.text).eq(String(n8) + ".0"); + + expect(stateVariables["/n1a"].stateValues.text).eq( + String(Math.round(n1 * 10 ** 8) / 10 ** 8), + ); + expect(stateVariables["/n2a"].stateValues.text).eq( + String(Math.round(n2 * 10 ** 1) / 10 ** 1), + ); + expect(stateVariables["/n3a"].stateValues.text).eq( + String(Math.round(n3 * 10 ** 3) / 10 ** 3), + ); + expect(stateVariables["/n4a"].stateValues.text).eq(String(n4) + ".0"); + + expect(stateVariables["/n5a"].stateValues.text).eq( + String(Math.round(n5 * 10 ** 8) / 10 ** 8), + ); + expect(stateVariables["/n6a"].stateValues.text).eq( + String(Math.round(n6 * 10 ** 1) / 10 ** 1), + ); + expect(stateVariables["/n7a"].stateValues.text).eq( + String(Math.round(n7 * 10 ** 3) / 10 ** 3), + ); + expect(stateVariables["/n8a"].stateValues.text).eq(String(n8) + ".0"); + }); + + it("copying parameters", async () => { + let core = await createTestCore({ + doenetML: ` +

Number of samples

+

Specified type of random number

+

Specified mean

+

Specified variance

+

Specified from

+

Specified to

+

Specified step

+

Actual type: $samples.type{obtainPropFromComposite assignNames="actualType"}

+

Actual from: $samples.from{obtainPropFromComposite assignNames="actualFrom"}

+

Actual to: $samples.to{obtainPropFromComposite assignNames="actualTo"}

+

Actual step: $samples.step{obtainPropFromComposite assignNames="actualStep"}

+

Expected mean: $samples.mean{obtainPropFromComposite assignNames="expectedMean" displayDigits="10"}

+

Expected variance: $samples.variance{obtainPropFromComposite assignNames="expectedVariance" displayDigits="10"}

+

Expected standard deviation: $samples.standardDeviation{obtainPropFromComposite assignNames="expectedStandardDeviation" displayDigits="10"}

+

Resulting mean: $samples

+

Resulting variance: $samples

+

Resulting standard deviation: $samples

+

+ +

+

$samples

+ + $p1{name="p3"} + $p2{name="p4"} + + $p3{name="p5"} + $p4{name="p6"} + `, + }); + + let checkSamples = function ({ + numSamples, + specifiedType, + specifiedMean, + specifiedVariance, + specifiedFrom, + specifiedTo, + specifiedStep, + sampleComponent, + allowedErrorInMean, + allowedErrorInVariance, + checkAllSamples = true, + stateVariables, + }) { + let nReplacements = sampleComponent.replacements.length; + if (sampleComponent.replacementsToWithhold) { + nReplacements -= sampleComponent.replacementsToWithhold; + } + let samples = sampleComponent.replacements + .slice(0, nReplacements) + .map((x) => stateVariables[x.componentName].stateValues.value); + expect(samples.length).eq(numSamples); + + expect(stateVariables["/numSamples"].stateValues.value.tree).eq( + numSamples, + ); + expect(stateVariables["/type"].stateValues.value).eq(specifiedType); + expect(stateVariables["/specifiedMean"].stateValues.value.tree).eq( + specifiedMean, + ); + expect( + stateVariables["/specifiedVariance"].stateValues.value.tree, + ).eq(specifiedVariance); + expect(stateVariables["/specifiedFrom"].stateValues.value.tree).eq( + specifiedFrom, + ); + expect(stateVariables["/specifiedTo"].stateValues.value.tree).eq( + specifiedTo, + ); + expect(stateVariables["/specifiedStep"].stateValues.value.tree).eq( + specifiedStep, + ); + + let type = specifiedType.toLowerCase(); + if (!["gaussian", "uniform", "discreteuniform"].includes(type)) { + type = "uniform"; + } + + expect(stateVariables["/actualType"].stateValues.value).eq(type); + + let from = specifiedFrom; + let to = specifiedTo; + let step = specifiedStep; + let expectedMean = specifiedMean; + let expectedVariance = specifiedVariance; + + if (type === "uniform") { + step = NaN; + expectedMean = (to + from) / 2; + expectedVariance = (to - from) ** 2 / 12; + } else if (type === "discreteuniform") { + to = from + Math.floor((to - from) / step) * step; + expectedMean = (to + from) / 2; + expectedVariance = + ((((to - from) / step + 1) ** 2 - 1) * step ** 2) / 12; + } else { + from = NaN; + to = NaN; + step = NaN; + } + + let expectedStandardDeviation = Math.sqrt(expectedVariance); + + expect(stateVariables["/actualFrom"].stateValues.value).eqls(from); + expect(stateVariables["/actualTo"].stateValues.value).eqls(to); + expect(stateVariables["/actualStep"].stateValues.value).eqls(step); + expect(stateVariables["/expectedMean"].stateValues.value).closeTo( + expectedMean, + 1e-12, + ); + expect( + stateVariables["/expectedVariance"].stateValues.value, + ).closeTo(expectedVariance, 1e-12); + expect( + stateVariables["/expectedStandardDeviation"].stateValues.value, + ).closeTo(expectedStandardDeviation, 1e-12); + + let resultingMean = me.math.mean(samples); + let resultingVariance = me.math.variance(samples); + let resultingStandardDeviation = Math.sqrt(resultingVariance); + + expect( + stateVariables["/resultingMean"].stateValues.value.tree, + ).closeTo(resultingMean, 1e-12); + expect(resultingMean).closeTo(expectedMean, allowedErrorInMean); + + expect( + stateVariables["/resultingVariance"].stateValues.value.tree, + ).closeTo(resultingVariance, 1e-12); + expect(resultingVariance).closeTo( + expectedVariance, + allowedErrorInVariance, + ); + + expect( + stateVariables["/resultingStandardDeviation"].stateValues.value + .tree, + ).closeTo(resultingStandardDeviation, 1e-12); + expect(resultingStandardDeviation).closeTo( + expectedStandardDeviation, + Math.sqrt(allowedErrorInVariance), + ); + + if (checkAllSamples) { + for (let ind = 1; ind <= 6; ind++) { + let numbers = stateVariables[`/p${ind}`].stateValues.text + .split(",") + .map(Number); + + expect(numbers.length).eq(numSamples); + for (let [i, num] of numbers.entries()) { + expect(num).closeTo(samples[i], 1e-8); + } + } + } + }; + + let numSamples = 10; + let specifiedType = ""; + let specifiedMean = 0; + let specifiedVariance = 1; + let specifiedFrom = 0; + let specifiedTo = 1; + let specifiedStep = 1; + + // initial values + let stateVariables = await returnAllStateVariables(core); + + checkSamples({ + numSamples, + specifiedType, + specifiedMean, + specifiedVariance, + specifiedFrom, + specifiedTo, + specifiedStep, + sampleComponent: stateVariables["/samples"], + allowedErrorInMean: 0.4, + allowedErrorInVariance: 0.4, + stateVariables, + }); + + // Increase number of samples + numSamples = 50; + await updateMathInputValue({ + latex: numSamples.toString(), + componentName: "/numSamples", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + checkSamples({ + numSamples, + specifiedType, + specifiedMean, + specifiedVariance, + specifiedFrom, + specifiedTo, + specifiedStep, + sampleComponent: stateVariables["/samples"], + allowedErrorInMean: 0.2, + allowedErrorInVariance: 0.2, + checkAllSamples: false, + stateVariables, + }); + + // change from and to + specifiedFrom = -3; + specifiedTo = 0; + await updateMathInputValue({ + latex: specifiedFrom.toString(), + componentName: "/specifiedFrom", + core, + }); + await updateMathInputValue({ + latex: specifiedTo.toString(), + componentName: "/specifiedTo", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + checkSamples({ + numSamples, + specifiedType, + specifiedMean, + specifiedVariance, + specifiedFrom, + specifiedTo, + specifiedStep, + sampleComponent: stateVariables["/samples"], + allowedErrorInMean: 0.4, + allowedErrorInVariance: 0.4, + checkAllSamples: false, + stateVariables, + }); + + // change type to discrete uniform + specifiedType = "discreteUniform"; + + await updateTextInputValue({ + text: specifiedType, + componentName: "/type", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + checkSamples({ + numSamples, + specifiedType, + specifiedMean, + specifiedVariance, + specifiedFrom, + specifiedTo, + specifiedStep, + sampleComponent: stateVariables["/samples"], + allowedErrorInMean: 0.4, + allowedErrorInVariance: 0.4, + checkAllSamples: false, + stateVariables, + }); + + // change from, to, and step + specifiedFrom = 3; + specifiedTo = -8; + specifiedStep = -4; + + await updateMathInputValue({ + latex: specifiedFrom.toString(), + componentName: "/specifiedFrom", + core, + }); + await updateMathInputValue({ + latex: specifiedTo.toString(), + componentName: "/specifiedTo", + core, + }); + await updateMathInputValue({ + latex: specifiedStep.toString(), + componentName: "/specifiedStep", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + checkSamples({ + numSamples, + specifiedType, + specifiedMean, + specifiedVariance, + specifiedFrom, + specifiedTo, + specifiedStep, + sampleComponent: stateVariables["/samples"], + allowedErrorInMean: 1.5, + allowedErrorInVariance: 3, + checkAllSamples: false, + stateVariables, + }); + + // change type to gaussian + specifiedType = "gaussian"; + + await updateTextInputValue({ + text: specifiedType, + componentName: "/type", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + checkSamples({ + numSamples, + specifiedType, + specifiedMean, + specifiedVariance, + specifiedFrom, + specifiedTo, + specifiedStep, + sampleComponent: stateVariables["/samples"], + allowedErrorInMean: 0.8, + allowedErrorInVariance: 0.8, + checkAllSamples: false, + stateVariables, + }); + + // change mean and variance + specifiedMean = -11; + specifiedVariance = 3; + + await updateMathInputValue({ + latex: specifiedMean.toString(), + componentName: "/specifiedMean", + core, + }); + await updateMathInputValue({ + latex: specifiedVariance.toString(), + componentName: "/specifiedVariance", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + checkSamples({ + numSamples, + specifiedType, + specifiedMean, + specifiedVariance, + specifiedFrom, + specifiedTo, + specifiedStep, + sampleComponent: stateVariables["/samples"], + allowedErrorInMean: 0.8, + allowedErrorInVariance: 3, + checkAllSamples: false, + stateVariables, + }); + + // Increase number of samples + numSamples = 200; + await updateMathInputValue({ + latex: numSamples.toString(), + componentName: "/numSamples", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + checkSamples({ + numSamples, + specifiedType, + specifiedMean, + specifiedVariance, + specifiedFrom, + specifiedTo, + specifiedStep, + sampleComponent: stateVariables["/samples"], + allowedErrorInMean: 0.4, + allowedErrorInVariance: 0.8, + checkAllSamples: false, + stateVariables, + }); + + // Decrease number of samples + numSamples = 20; + await updateMathInputValue({ + latex: numSamples.toString(), + componentName: "/numSamples", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + checkSamples({ + numSamples, + specifiedType, + specifiedMean, + specifiedVariance, + specifiedFrom, + specifiedTo, + specifiedStep, + sampleComponent: stateVariables["/samples"], + allowedErrorInMean: 1, + allowedErrorInVariance: 3, + checkAllSamples: true, + stateVariables, + }); + }); + + it("same numbers for given variant if variantDeterminesSeed", async () => { + let doenetML = ` +

+ + +

+ + `; + + let core = await createTestCore({ + doenetML, + requestedVariantIndex: 1, + }); + + let stateVariables = await returnAllStateVariables(core); + + let samples = stateVariables["/p1"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + + expect(samples.length).eq(100); + + for (let sample of samples) { + expect(sample).gt(0); + expect(sample).lte(1); + } + + core = await createTestCore({ + doenetML, + requestedVariantIndex: 1, + }); + + stateVariables = await returnAllStateVariables(core); + + let samples2 = stateVariables["/p1"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + + expect(samples2).eqls(samples); + + core = await createTestCore({ + doenetML, + requestedVariantIndex: 2, + }); + + stateVariables = await returnAllStateVariables(core); + + samples2 = stateVariables["/p1"].activeChildren.map( + (x) => stateVariables[x.componentName].stateValues.value, + ); + + expect(samples2.length).eq(100); + + for (let [ind, sample] of samples2.entries()) { + expect(sample).gt(0); + expect(sample).lte(1); + expect(sample).not.eq(samples[ind]); + } + }); + + it(`resample random numbers`, async () => { + let core = await createTestCore({ + doenetML: ` +

, + +

+ +

+ + +

+ + `, + }); + + let rn1, rn2, rn3; + let rn1b, rn2b, rn3b; + + let stateVariables = await returnAllStateVariables(core); + + rn1 = stateVariables["/rn1"].stateValues.value; + rn2 = stateVariables["/rn2"].stateValues.value; + rn3 = stateVariables["/rn3"].stateValues.value; + + expect(rn1).gt(1).lt(10); + expect(rn2).gt(1).lt(10); + expect(rn3).gt(1000).lt(10000); + + let rn1Rounded = Math.round(rn1 * 100) / 100; + + expect(stateVariables["/rn1"].stateValues.text).eq( + rn1Rounded.toString(), + ); + + await core.requestAction({ + componentName: "/resamp1", + actionName: "callAction", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + rn1b = stateVariables["/rn1"].stateValues.value; + rn2b = stateVariables["/rn2"].stateValues.value; + rn3b = stateVariables["/rn3"].stateValues.value; + + expect(rn1b).gt(1).lt(10); + expect(rn2b).gt(1).lt(10); + expect(rn3b).gt(1000).lt(10000); + + expect(rn1b).not.eq(rn1); + expect(rn2b).not.eq(rn2); + expect(rn3b).eq(rn3); + + let rn3Rounded = Math.round(rn3 * 100) / 100; + + expect(stateVariables["/rn3"].stateValues.text).eq( + rn3Rounded.toString(), + ); + + await core.requestAction({ + componentName: "/resamp2", + actionName: "callAction", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + let rn1c = stateVariables["/rn1"].stateValues.value; + let rn2c = stateVariables["/rn2"].stateValues.value; + let rn3c = stateVariables["/rn3"].stateValues.value; + + expect(rn1c).gt(1).lt(10); + expect(rn2c).gt(1).lt(10); + expect(rn3c).gt(1000).lt(10000); + + expect(rn1c).eq(rn1b); + expect(rn2c).eq(rn2b); + expect(rn3c).not.eq(rn3); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/sequence.test.ts b/packages/doenetml-worker/src/test/tagSpecific/sequence.test.ts new file mode 100644 index 000000000..06ed1b6eb --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/sequence.test.ts @@ -0,0 +1,1748 @@ +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("Sequence tag tests", async () => { + it("number sequence, no parameters", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(10); + for (let i = 0; i < 10; i++) { + expect(children[i].stateValues.value).eq(i + 1); + } + }); + + it("number sequence, just from", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(10); + for (let i = 0; i < 10; i++) { + expect(children[i].stateValues.value).eq(i - 4); + } + }); + + it("number sequence, just to", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(3); + for (let i = 0; i < 3; i++) { + expect(children[i].stateValues.value).eq(3 + i - 2); + } + }); + + it("number sequence, just step", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(10); + for (let i = 0; i < 10; i++) { + expect(children[i].stateValues.value).eq(1 + i * -2); + } + }); + + it("number sequence, just length", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(5); + for (let i = 0; i < 5; i++) { + expect(children[i].stateValues.value).eq(1 + i); + } + }); + + it("number sequence, from and to", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(8); + for (let i = 0; i < 8; i++) { + expect(children[i].stateValues.value).eq(-3 + i); + } + }); + + it("number sequence, from and to, not matching", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(8); + for (let i = 0; i < 8; i++) { + expect(children[i].stateValues.value).eq(-3 + i); + } + }); + + it("number sequence, from and to, adjust for round-off error", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(8); + for (let i = 0; i < 8; i++) { + expect(children[i].stateValues.value).eq(i + 1); + } + }); + + it("math sequence, from and to, adjust for round-off error", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(8); + for (let i = 0; i < 8; i++) { + expect(children[i].stateValues.value.tree).eq(i + 1); + } + }); + + it("number sequence, from and step", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(10); + for (let i = 0; i < 10; i++) { + expect(children[i].stateValues.value).eq(2 + i * -4); + } + }); + + it("number sequence, from and length", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(3); + for (let i = 0; i < 3; i++) { + expect(children[i].stateValues.value).eq(11 + i); + } + }); + + it("number sequence, to and step", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(7); + for (let i = 0; i < 7; i++) { + expect(children[i].stateValues.value).eq(21 + 3 * (i - 6)); + } + }); + + it("number sequence, to and step, adjust for round-off error", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(5); + for (let i = 0; i < 5; i++) { + expect( + Math.abs(children[i].stateValues.value - (1 + i * 0.1)), + ).lessThan(1e-14); + } + }); + + it("math sequence, to and step, adjust for round-off error", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(5); + for (let i = 0; i < 5; i++) { + expect( + Math.abs(children[i].stateValues.value - (1 + i * 0.1)), + ).lessThan(1e-14); + } + }); + + it("number sequence, to and length", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(4); + for (let i = 0; i < 4; i++) { + expect(children[i].stateValues.value).eq(-8 + (i - 3)); + } + }); + + it("number sequence, step and length", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(6); + for (let i = 0; i < 6; i++) { + expect(children[i].stateValues.value).eq(1 + 5 * i); + } + }); + + it("number sequence, from, to, and step", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(4); + for (let i = 0; i < 4; i++) { + expect(children[i].stateValues.value).eq(9 - 2 * i); + } + }); + + it("number sequence, from, to, and step, adjust for round-off errors", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let sequence = [0.2, 0.3, 0.4, 0.5]; + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(4); + for (let i = 0; i < 4; i++) { + expect( + Math.abs(children[i].stateValues.value - sequence[i]), + ).lessThan(1e-14); + } + }); + + it("math sequence, from, to, and step, adjust for round-off errors", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let sequence = [0.2, 0.3, 0.4, 0.5]; + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(4); + for (let i = 0; i < 4; i++) { + expect( + Math.abs(children[i].stateValues.value - sequence[i]), + ).lessThan(1e-14); + } + }); + + it("number sequence, from, to, and length", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(6); + for (let i = 0; i < 6; i++) { + expect(children[i].stateValues.value).eq(-5 + 2 * i); + } + }); + + it("number sequence, from, step, and length", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(5); + for (let i = 0; i < 5; i++) { + expect(children[i].stateValues.value).eq(8 - 2 * i); + } + }); + + it("number sequence, to, step, and length", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(5); + for (let i = 0; i < 5; i++) { + expect(children[i].stateValues.value).eq(8 - 2 * (i - 4)); + } + }); + + it("letters sequence, lowercase", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(5); + expect(children[0].stateValues.value).eq("c"); + expect(children[1].stateValues.value).eq("f"); + expect(children[2].stateValues.value).eq("i"); + expect(children[3].stateValues.value).eq("l"); + expect(children[4].stateValues.value).eq("o"); + }); + + it("letters sequence, uppercase", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(5); + expect(children[0].stateValues.value).eq("Y"); + expect(children[1].stateValues.value).eq("U"); + expect(children[2].stateValues.value).eq("Q"); + expect(children[3].stateValues.value).eq("M"); + expect(children[4].stateValues.value).eq("I"); + }); + + it("letters sequence, multicharacter", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(4); + expect(children[0].stateValues.value).eq("az"); + expect(children[1].stateValues.value).eq("bc"); + expect(children[2].stateValues.value).eq("bf"); + expect(children[3].stateValues.value).eq("bi"); + }); + + it("letters sequence, stays valid", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(6); + expect(children[0].stateValues.value).eq("b"); + expect(children[1].stateValues.value).eq("e"); + expect(children[2].stateValues.value).eq("h"); + expect(children[3].stateValues.value).eq("k"); + expect(children[4].stateValues.value).eq("n"); + expect(children[5].stateValues.value).eq("q"); + }); + + it("letters sequence, no parameters", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(10); + expect(children[0].stateValues.value).eq("a"); + expect(children[1].stateValues.value).eq("b"); + expect(children[2].stateValues.value).eq("c"); + expect(children[3].stateValues.value).eq("d"); + expect(children[4].stateValues.value).eq("e"); + expect(children[5].stateValues.value).eq("f"); + expect(children[6].stateValues.value).eq("g"); + expect(children[7].stateValues.value).eq("h"); + expect(children[8].stateValues.value).eq("i"); + expect(children[9].stateValues.value).eq("j"); + }); + + it("math sequence, calculate step", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(4); + expect(children[0].stateValues.value.tree).eqls(["*", 3, "x"]); + expect(children[1].stateValues.value.tree).eqls([ + "+", + ["*", 2, "x"], + "y", + ]); + expect(children[2].stateValues.value.tree).eqls([ + "+", + "x", + ["*", 2, "y"], + ]); + expect(children[3].stateValues.value.tree).eqls(["*", 3, "y"]); + }); + + it("number sequence, excludes", async () => { + let core = await createTestCore({ + doenetML: ` +

+

Also exclude:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(8); + let ind = 0; + for (let i = 0; i < 10; i++) { + if (i == 1 || i == 7) { + continue; + } + expect(children[ind].stateValues.value).eq(i - 1); + ind++; + } + + // also exclude 7 + await updateMathInputValue({ + latex: "7", + componentName: "/exclude2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(7); + ind = 0; + for (let i = 0; i < 10; i++) { + if (i == 1 || i == 7 || i == 8) { + continue; + } + expect(children[ind].stateValues.value).eq(i - 1); + ind++; + } + + // also exclude 6 twice + await updateMathInputValue({ + latex: "6", + componentName: "/exclude2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(8); + ind = 0; + for (let i = 0; i < 10; i++) { + if (i == 1 || i == 7) { + continue; + } + expect(children[ind].stateValues.value).eq(i - 1); + ind++; + } + + // also exclude 12 + await updateMathInputValue({ + latex: "12", + componentName: "/exclude2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(8); + ind = 0; + for (let i = 0; i < 10; i++) { + if (i == 1 || i == 7) { + continue; + } + expect(children[ind].stateValues.value).eq(i - 1); + ind++; + } + + // also exclude 3 + await updateMathInputValue({ + latex: "3", + componentName: "/exclude2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(7); + ind = 0; + for (let i = 0; i < 10; i++) { + if (i == 1 || i == 7 || i == 4) { + continue; + } + expect(children[ind].stateValues.value).eq(i - 1); + ind++; + } + + // don't exclude anything else + await updateMathInputValue({ + latex: "", + componentName: "/exclude2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(8); + ind = 0; + for (let i = 0; i < 10; i++) { + if (i == 1 || i == 7) { + continue; + } + expect(children[ind].stateValues.value).eq(i - 1); + ind++; + } + }); + + it("number sequence, excludes, adjust for round-off errors", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let sequence = [0.1, 0.2, 0.4, 0.5, 0.8]; + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(5); + for (let i = 0; i < 5; i++) { + expect( + Math.abs(children[i].stateValues.value - sequence[i]), + ).lessThan(1e-14); + } + }); + + it("letters sequence, excludes", async () => { + let core = await createTestCore({ + doenetML: ` +

+

Also exclude:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(8); + let ind = 0; + for (let i = 0; i < 10; i++) { + if (i == 1 || i == 5) { + continue; + } + expect(children[ind].stateValues.value).eq( + String.fromCharCode(97 + i), + ); + ind++; + } + + // also exclude i + await updateTextInputValue({ text: "i", componentName: "/e", core }); + stateVariables = await returnAllStateVariables(core); + children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(7); + ind = 0; + for (let i = 0; i < 10; i++) { + if (i == 1 || i == 5 || i == 8) { + continue; + } + expect(children[ind].stateValues.value).eq( + String.fromCharCode(97 + i), + ); + ind++; + } + + // also exclude f twice + await updateTextInputValue({ text: "f", componentName: "/e", core }); + + stateVariables = await returnAllStateVariables(core); + children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(8); + ind = 0; + for (let i = 0; i < 10; i++) { + if (i == 1 || i == 5) { + continue; + } + expect(children[ind].stateValues.value).eq( + String.fromCharCode(97 + i), + ); + ind++; + } + + // also exclude l + await updateTextInputValue({ text: "l", componentName: "/e", core }); + + stateVariables = await returnAllStateVariables(core); + children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(8); + ind = 0; + for (let i = 0; i < 10; i++) { + if (i == 1 || i == 5) { + continue; + } + expect(children[ind].stateValues.value).eq( + String.fromCharCode(97 + i), + ); + ind++; + } + + // also exclude C + await updateTextInputValue({ text: "C", componentName: "/e", core }); + + stateVariables = await returnAllStateVariables(core); + children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(7); + ind = 0; + for (let i = 0; i < 10; i++) { + if (i == 1 || i == 5 || i == 2) { + continue; + } + expect(children[ind].stateValues.value).eq( + String.fromCharCode(97 + i), + ); + ind++; + } + + // don't exclude anything else + await updateTextInputValue({ text: "", componentName: "/e", core }); + + stateVariables = await returnAllStateVariables(core); + children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(8); + ind = 0; + for (let i = 0; i < 10; i++) { + if (i == 1 || i == 5) { + continue; + } + expect(children[ind].stateValues.value).eq( + String.fromCharCode(97 + i), + ); + ind++; + } + }); + + it("math sequence, excludes", async () => { + let core = await createTestCore({ + doenetML: ` +

+

Also exclude:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(8); + let ind = 0; + for (let i = 0; i < 10; i++) { + if (i == 1 || i == 5) { + continue; + } + expect( + me + .fromAst(children[ind].stateValues.value) + .equals(me.fromText((1 + i).toString() + "x")), + ).eq(true); + ind++; + } + + // also exclude 9x + await updateMathInputValue({ latex: "9x", componentName: "/e", core }); + + stateVariables = await returnAllStateVariables(core); + children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(7); + ind = 0; + for (let i = 0; i < 10; i++) { + if (i == 1 || i == 5 || i == 8) { + continue; + } + expect( + me + .fromAst(children[ind].stateValues.value) + .equals(me.fromText((1 + i).toString() + "x")), + ).eq(true); + ind++; + } + + // also exclude 6x twice + await updateMathInputValue({ latex: "6x", componentName: "/e", core }); + + stateVariables = await returnAllStateVariables(core); + children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(8); + ind = 0; + for (let i = 0; i < 10; i++) { + if (i == 1 || i == 5) { + continue; + } + expect( + me + .fromAst(children[ind].stateValues.value) + .equals(me.fromText((1 + i).toString() + "x")), + ).eq(true); + ind++; + } + + // also exclude 12x + await updateMathInputValue({ latex: "12x", componentName: "/e", core }); + + stateVariables = await returnAllStateVariables(core); + children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(8); + ind = 0; + for (let i = 0; i < 10; i++) { + if (i == 1 || i == 5) { + continue; + } + expect( + me + .fromAst(children[ind].stateValues.value) + .equals(me.fromText((1 + i).toString() + "x")), + ).eq(true); + ind++; + } + + // also exclude 3x + await updateMathInputValue({ latex: "3x", componentName: "/e", core }); + + stateVariables = await returnAllStateVariables(core); + children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(7); + ind = 0; + for (let i = 0; i < 10; i++) { + if (i == 1 || i == 5 || i == 2) { + continue; + } + expect( + me + .fromAst(children[ind].stateValues.value) + .equals(me.fromText((1 + i).toString() + "x")), + ).eq(true); + ind++; + } + + // don't exclude anything else + await updateMathInputValue({ latex: "", componentName: "/e", core }); + + stateVariables = await returnAllStateVariables(core); + children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(8); + ind = 0; + for (let i = 0; i < 10; i++) { + if (i == 1 || i == 5) { + continue; + } + expect( + me + .fromAst(children[ind].stateValues.value) + .equals(me.fromText((1 + i).toString() + "x")), + ).eq(true); + ind++; + } + }); + + it("math sequence, excludes, adjust for round-off errors", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let sequence = [0.1, 0.2, 0.4, 0.5, 0.8]; + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(5); + for (let i = 0; i < 5; i++) { + expect( + Math.abs(children[i].stateValues.value - sequence[i]), + ).lessThan(1e-14); + } + }); + + it("sequence of decimals rounds on display", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + // Round when displaying to show 10ths correctly + // But, don't round internally + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(11); + + for (let i = 0; i < 11; i++) { + // Note: i/10 is rounded to have one decimal + // but 0.1*i can have extra decimals due to round-off errors + expect(children[i].stateValues.valueForDisplay).eq(i / 10); + expect(children[i].stateValues.value).eq(0.1 * i); + } + }); + + it("sequence with number operators", async () => { + let core = await createTestCore({ + doenetML: ` + 5 + 10 +

+ + $n11 + + + $m+311 + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(9); + + for (let i = 0; i < 9; i++) { + expect(children[i].stateValues.valueForDisplay).eq(i + 5); + expect(children[i].stateValues.value).eq(i + 5); + } + }); + + it("initially invalid to", async () => { + let core = await createTestCore({ + doenetML: ` + +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/seq"].stateValues.validSequence).eq(false); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(0); + + await updateMathInputValue({ latex: "2", componentName: "/n", core }); + + stateVariables = await returnAllStateVariables(core); + children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(1); + expect(stateVariables[children[0].componentName].stateValues.value).eq( + 2, + ); + expect(stateVariables["/seq"].stateValues.validSequence).eq(true); + }); + + it("number sequence, excluding every 3 plus another", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p"].stateValues.text).eq("1, 3, 4, 6, 7, 10"); + }); + + it("number sequence, excluding from different sources", async () => { + let core = await createTestCore({ + doenetML: ` + 4 62 87 +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p"].stateValues.text).eq("1, 3, 5, 9, 10"); + }); + + it("sequences hide dynamically", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + +

Length of sequence 1:

+

Length of sequence 2:

+ +

sequence 1:

+

sequence 2:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s1"].stateValues.text).eq( + "sequence 1: 1, 2, 3, 4", + ); + expect(stateVariables["/s2"].stateValues.text).eq("sequence 2: "); + + await updateMathInputValue({ latex: "6", componentName: "/n1", core }); + await updateMathInputValue({ latex: "6", componentName: "/n2", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s1"].stateValues.text).eq( + "sequence 1: 1, 2, 3, 4, 5, 6", + ); + expect(stateVariables["/s2"].stateValues.text).eq("sequence 2: "); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/h1", + core, + }); + await updateBooleanInputValue({ + boolean: false, + componentName: "/h2", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s1"].stateValues.text).eq("sequence 1: "); + expect(stateVariables["/s2"].stateValues.text).eq( + "sequence 2: 1, 2, 3, 4, 5, 6", + ); + + await updateMathInputValue({ latex: "8", componentName: "/n1", core }); + await updateMathInputValue({ latex: "8", componentName: "/n2", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s1"].stateValues.text).eq("sequence 1: "); + expect(stateVariables["/s2"].stateValues.text).eq( + "sequence 2: 1, 2, 3, 4, 5, 6, 7, 8", + ); + + await updateBooleanInputValue({ + boolean: false, + componentName: "/h1", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/h2", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s1"].stateValues.text).eq( + "sequence 1: 1, 2, 3, 4, 5, 6, 7, 8", + ); + expect(stateVariables["/s2"].stateValues.text).eq("sequence 2: "); + + await updateMathInputValue({ latex: "3", componentName: "/n1", core }); + await updateMathInputValue({ latex: "3", componentName: "/n2", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s1"].stateValues.text).eq( + "sequence 1: 1, 2, 3", + ); + expect(stateVariables["/s2"].stateValues.text).eq("sequence 2: "); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/h1", + core, + }); + await updateBooleanInputValue({ + boolean: false, + componentName: "/h2", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s1"].stateValues.text).eq("sequence 1: "); + expect(stateVariables["/s2"].stateValues.text).eq( + "sequence 2: 1, 2, 3", + ); + + await updateMathInputValue({ latex: "4", componentName: "/n1", core }); + await updateMathInputValue({ latex: "4", componentName: "/n2", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/s1"].stateValues.text).eq("sequence 1: "); + expect(stateVariables["/s2"].stateValues.text).eq( + "sequence 2: 1, 2, 3, 4", + ); + }); + + it("sequence fixed by default", async () => { + let core = await createTestCore({ + doenetML: ` +

From:

+

Step:

+ +

+ +

Change first:

+

Change second:

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("1, 3, 5, 7"); + + await updateMathInputValue({ latex: "21", componentName: "/a2", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("1, 3, 5, 7"); + + await updateMathInputValue({ latex: "2", componentName: "/b2", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("1, 3, 5, 7"); + + await updateMathInputValue({ + latex: "4", + componentName: "/from", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("4, 6"); + + await updateMathInputValue({ latex: "8", componentName: "/a2", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("4, 6"); + + await updateMathInputValue({ latex: "2", componentName: "/b2", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("4, 6"); + + await updateMathInputValue({ + latex: "6", + componentName: "/step", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("4"); + + await updateMathInputValue({ latex: "9", componentName: "/a2", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("4"); + + await updateMathInputValue({ latex: "41", componentName: "/b2", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("4"); + }); + + it("can override fixed property", async () => { + let core = await createTestCore({ + doenetML: ` +

From:

+

Step:

+

Fixed:

+ +

+ +

Change first:

+

Change second:

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("1, 3, 5, 7"); + + await updateMathInputValue({ latex: "21", componentName: "/a2", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("21, 3, 5, 7"); + + await updateMathInputValue({ latex: "0", componentName: "/b2", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("21, 0, 5, 7"); + + await updateMathInputValue({ + latex: "4", + componentName: "/from", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("4, 6"); + + await updateMathInputValue({ latex: "8", componentName: "/a2", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("8, 6"); + + await updateMathInputValue({ latex: "2", componentName: "/b2", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("8, 2"); + + await updateMathInputValue({ + latex: "6", + componentName: "/step", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("4"); + + await updateMathInputValue({ latex: "9", componentName: "/a2", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("9"); + + await updateMathInputValue({ latex: "41", componentName: "/b2", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("9"); + + await updateBooleanInputValue({ + boolean: true, + componentName: "/fx", + core, + }); + + await updateMathInputValue({ + latex: "1", + componentName: "/step", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("4, 5, 6, 7"); + + await updateMathInputValue({ latex: "9", componentName: "/a2", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("4, 5, 6, 7"); + + await updateMathInputValue({ latex: "41", componentName: "/b2", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("4, 5, 6, 7"); + + await updateBooleanInputValue({ + boolean: false, + componentName: "/fx", + core, + }); + + await updateMathInputValue({ latex: "9", componentName: "/a2", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("9, 5, 6, 7"); + + await updateMathInputValue({ latex: "41", componentName: "/b2", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("9, 41, 6, 7"); + }); + + it('copies with link="false" are not fixed', async () => { + let core = await createTestCore({ + doenetML: ` +

From:

+

Step:

+ +

+ +

Change first:

+

Change second:

+ +

Copy of a2: $a2{name="a3"}

+

Copy of b2: $b2{name="b3"}

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("1, 3, 5, 7"); + expect(stateVariables["/a2"].stateValues.value.tree).eq(1); + expect(stateVariables["/b2"].stateValues.value.tree).eq(3); + expect(stateVariables["/a3"].stateValues.value.tree).eq(1); + expect(stateVariables["/b3"].stateValues.value.tree).eq(3); + + await updateMathInputValue({ latex: "21", componentName: "/a2", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("1, 3, 5, 7"); + expect(stateVariables["/a2"].stateValues.value.tree).eq(21); + expect(stateVariables["/b2"].stateValues.value.tree).eq(3); + expect(stateVariables["/a3"].stateValues.value.tree).eq(21); + expect(stateVariables["/b3"].stateValues.value.tree).eq(3); + + await updateMathInputValue({ latex: "0", componentName: "/b2", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("1, 3, 5, 7"); + expect(stateVariables["/a2"].stateValues.value.tree).eq(21); + expect(stateVariables["/b2"].stateValues.value.tree).eq(0); + expect(stateVariables["/a3"].stateValues.value.tree).eq(21); + expect(stateVariables["/b3"].stateValues.value.tree).eq(0); + + await updateMathInputValue({ + latex: "4", + componentName: "/from", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("4, 6"); + expect(stateVariables["/a2"].stateValues.value.tree).eq(21); + expect(stateVariables["/b2"].stateValues.value.tree).eq(0); + expect(stateVariables["/a3"].stateValues.value.tree).eq(21); + expect(stateVariables["/b3"].stateValues.value.tree).eq(0); + + await updateMathInputValue({ latex: "8", componentName: "/a2", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("4, 6"); + expect(stateVariables["/a2"].stateValues.value.tree).eq(8); + expect(stateVariables["/b2"].stateValues.value.tree).eq(0); + expect(stateVariables["/a3"].stateValues.value.tree).eq(8); + expect(stateVariables["/b3"].stateValues.value.tree).eq(0); + + await updateMathInputValue({ + latex: "6", + componentName: "/step", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("4"); + expect(stateVariables["/a2"].stateValues.value.tree).eq(8); + expect(stateVariables["/b2"].stateValues.value.tree).eq(0); + expect(stateVariables["/a3"].stateValues.value.tree).eq(8); + expect(stateVariables["/b3"].stateValues.value.tree).eq(0); + + await updateMathInputValue({ latex: "9", componentName: "/a2", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("4"); + expect(stateVariables["/a2"].stateValues.value.tree).eq(9); + expect(stateVariables["/b2"].stateValues.value.tree).eq(0); + expect(stateVariables["/a3"].stateValues.value.tree).eq(9); + expect(stateVariables["/b3"].stateValues.value.tree).eq(0); + + await updateMathInputValue({ latex: "2", componentName: "/b2", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("4"); + expect(stateVariables["/a2"].stateValues.value.tree).eq(9); + expect(stateVariables["/b2"].stateValues.value.tree).eq(2); + expect(stateVariables["/a3"].stateValues.value.tree).eq(9); + expect(stateVariables["/b3"].stateValues.value.tree).eq(2); + + await updateMathInputValue({ + latex: "8", + componentName: "/from", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq(""); + expect(stateVariables["/a2"].stateValues.value.tree).eq(9); + expect(stateVariables["/b2"].stateValues.value.tree).eq(2); + expect(stateVariables["/a3"].stateValues.value.tree).eq(9); + expect(stateVariables["/b3"].stateValues.value.tree).eq(2); + + await updateMathInputValue({ latex: "3", componentName: "/a2", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq(""); + expect(stateVariables["/a2"].stateValues.value.tree).eq(3); + expect(stateVariables["/b2"].stateValues.value.tree).eq(2); + expect(stateVariables["/a3"].stateValues.value.tree).eq(3); + expect(stateVariables["/b3"].stateValues.value.tree).eq(2); + + await updateMathInputValue({ + latex: "3", + componentName: "/step", + core, + }); + await updateMathInputValue({ + latex: "0", + componentName: "/from", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("0, 3, 6"); + expect(stateVariables["/a2"].stateValues.value.tree).eq(3); + expect(stateVariables["/b2"].stateValues.value.tree).eq(2); + expect(stateVariables["/a3"].stateValues.value.tree).eq(3); + expect(stateVariables["/b3"].stateValues.value.tree).eq(2); + + await updateMathInputValue({ latex: "8", componentName: "/a2", core }); + await updateMathInputValue({ latex: "7", componentName: "/b2", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/theList"].stateValues.text).eq("0, 3, 6"); + expect(stateVariables["/a2"].stateValues.value.tree).eq(8); + expect(stateVariables["/b2"].stateValues.value.tree).eq(7); + expect(stateVariables["/a3"].stateValues.value.tree).eq(8); + expect(stateVariables["/b3"].stateValues.value.tree).eq(7); + }); + + it("number sequence, from and to using strings with operators", async () => { + let core = await createTestCore({ + doenetML: ` +

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(8); + for (let i = 0; i < 8; i++) { + expect(children[i].stateValues.value).eq(-3 + i); + } + }); + + it("number sequence, excludes with operators from macros", async () => { + let core = await createTestCore({ + doenetML: ` + 2 + 6 +

+ `, + }); + + let nums = [0, 1, 5, 6, 8]; + + let stateVariables = await returnAllStateVariables(core); + let children = stateVariables["/p"].activeChildren.map( + (x) => stateVariables[x.componentName], + ); + expect(children.length).eq(nums.length); + for (let [ind, child] of children.entries()) { + expect(child.stateValues.value).eq(nums[ind]); + } + }); + + it("warnings", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + + + + `, + }); + + let errorWarnings = core.errorWarnings; + + expect(errorWarnings.errors.length).eq(0); + expect(errorWarnings.warnings.length).eq(9); + + expect(errorWarnings.warnings[0].message).contain( + `Invalid length of sequence. Must be a non-negative integer`, + ); + expect(errorWarnings.warnings[0].level).eq(1); + expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(2); + expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(5); + expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(2); + expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(27); + + expect(errorWarnings.warnings[1].message).contain( + `Invalid step of sequence. Must be a number for sequence of type number`, + ); + expect(errorWarnings.warnings[1].level).eq(1); + expect(errorWarnings.warnings[1].doenetMLrange.lineBegin).eq(3); + expect(errorWarnings.warnings[1].doenetMLrange.charBegin).eq(5); + expect(errorWarnings.warnings[1].doenetMLrange.lineEnd).eq(3); + expect(errorWarnings.warnings[1].doenetMLrange.charEnd).eq(24); + + expect(errorWarnings.warnings[2].message).contain( + `Invalid step of sequence. Must be a number for sequence of type letters`, + ); + expect(errorWarnings.warnings[2].level).eq(1); + expect(errorWarnings.warnings[2].doenetMLrange.lineBegin).eq(4); + expect(errorWarnings.warnings[2].doenetMLrange.charBegin).eq(5); + expect(errorWarnings.warnings[2].doenetMLrange.lineEnd).eq(4); + expect(errorWarnings.warnings[2].doenetMLrange.charEnd).eq(40); + + expect(errorWarnings.warnings[3].message).contain( + `Invalid "from" of number sequence. Must be a number`, + ); + expect(errorWarnings.warnings[3].level).eq(1); + expect(errorWarnings.warnings[3].doenetMLrange.lineBegin).eq(5); + expect(errorWarnings.warnings[3].doenetMLrange.charBegin).eq(5); + expect(errorWarnings.warnings[3].doenetMLrange.lineEnd).eq(5); + expect(errorWarnings.warnings[3].doenetMLrange.charEnd).eq(25); + + expect(errorWarnings.warnings[4].message).contain( + `Invalid "from" of letters sequence. Must be a letter combination`, + ); + expect(errorWarnings.warnings[4].level).eq(1); + expect(errorWarnings.warnings[4].doenetMLrange.lineBegin).eq(6); + expect(errorWarnings.warnings[4].doenetMLrange.charBegin).eq(5); + expect(errorWarnings.warnings[4].doenetMLrange.lineEnd).eq(6); + expect(errorWarnings.warnings[4].doenetMLrange.charEnd).eq(40); + + expect(errorWarnings.warnings[5].message).contain( + `Invalid "from" of sequence`, + ); + expect(errorWarnings.warnings[5].level).eq(1); + expect(errorWarnings.warnings[5].doenetMLrange.lineBegin).eq(7); + expect(errorWarnings.warnings[5].doenetMLrange.charBegin).eq(5); + expect(errorWarnings.warnings[5].doenetMLrange.lineEnd).eq(7); + expect(errorWarnings.warnings[5].doenetMLrange.charEnd).eq(40); + + expect(errorWarnings.warnings[6].message).contain( + `Invalid "to" of number sequence. Must be a number.`, + ); + expect(errorWarnings.warnings[6].level).eq(1); + expect(errorWarnings.warnings[6].doenetMLrange.lineBegin).eq(8); + expect(errorWarnings.warnings[6].doenetMLrange.charBegin).eq(5); + expect(errorWarnings.warnings[6].doenetMLrange.lineEnd).eq(8); + expect(errorWarnings.warnings[6].doenetMLrange.charEnd).eq(23); + + expect(errorWarnings.warnings[7].message).contain( + `Invalid "to" of letters sequence. Must be a letter combination`, + ); + expect(errorWarnings.warnings[7].level).eq(1); + expect(errorWarnings.warnings[7].doenetMLrange.lineBegin).eq(9); + expect(errorWarnings.warnings[7].doenetMLrange.charBegin).eq(5); + expect(errorWarnings.warnings[7].doenetMLrange.lineEnd).eq(9); + expect(errorWarnings.warnings[7].doenetMLrange.charEnd).eq(38); + + expect(errorWarnings.warnings[8].message).contain( + `Invalid "to" of sequence`, + ); + expect(errorWarnings.warnings[8].level).eq(1); + expect(errorWarnings.warnings[8].doenetMLrange.lineBegin).eq(10); + expect(errorWarnings.warnings[8].doenetMLrange.charBegin).eq(5); + expect(errorWarnings.warnings[8].doenetMLrange.lineEnd).eq(10); + expect(errorWarnings.warnings[8].doenetMLrange.charEnd).eq(38); + }); + + it("sequence displays as list by default", async () => { + let core = await createTestCore({ + doenetML: ` +

+

+

+

$default

+

$nocommas

+

$withcommas

+

$default{asList="false"}

+

$withcommas{asList="false"}

+

$nocommas{asList="true"}

+

+

+

+

+

+

+

+

+

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/pdefault"].stateValues.text).eq( + "1, 2, 3, 4, 5, 6, 7, 8, 9, 10", + ); + expect(stateVariables["/pdefault2"].stateValues.text).eq( + "1, 2, 3, 4, 5, 6, 7, 8, 9, 10", + ); + expect(stateVariables["/pdefault4"].stateValues.text).eq( + "1, 2, 3, 4, 5, 6, 7, 8, 9, 10", + ); + expect(stateVariables["/pdefault5"].stateValues.text).eq( + "1, 2, 3, 4, 5, 6, 7, 8, 9, 10", + ); + expect(stateVariables["/pnocommas"].stateValues.text).eq("12345678910"); + expect(stateVariables["/pnocommas2"].stateValues.text).eq( + "12345678910", + ); + expect(stateVariables["/pnocommas3"].stateValues.text).eq( + "12345678910", + ); + expect(stateVariables["/pnocommas3a"].stateValues.text).eq( + "12345678910", + ); + expect(stateVariables["/pnocommas4"].stateValues.text).eq( + "12345678910", + ); + expect(stateVariables["/pnocommas5"].stateValues.text).eq( + "12345678910", + ); + expect(stateVariables["/pnocommas6"].stateValues.text).eq( + "12345678910", + ); + expect(stateVariables["/pnocommas6a"].stateValues.text).eq( + "12345678910", + ); + expect(stateVariables["/pwithcommas"].stateValues.text).eq( + "1, 2, 3, 4, 5, 6, 7, 8, 9, 10", + ); + expect(stateVariables["/pwithcommas2"].stateValues.text).eq( + "1, 2, 3, 4, 5, 6, 7, 8, 9, 10", + ); + expect(stateVariables["/pwithcommas3"].stateValues.text).eq( + "1, 2, 3, 4, 5, 6, 7, 8, 9, 10", + ); + expect(stateVariables["/pwithcommas4"].stateValues.text).eq( + "1, 2, 3, 4, 5, 6, 7, 8, 9, 10", + ); + expect(stateVariables["/pwithcommas5"].stateValues.text).eq( + "1, 2, 3, 4, 5, 6, 7, 8, 9, 10", + ); + expect(stateVariables["/pwithcommas6"].stateValues.text).eq( + "1, 2, 3, 4, 5, 6, 7, 8, 9, 10", + ); + }); + + it("rounding", async () => { + let core = await createTestCore({ + doenetML: ` + a +

+

+

+

+ +

$n1a $n1b $n1c

+

$n2a $n2b $n2c

+

$n3a $n3b $n3c

+

$n4a $n4b $n4c

+ + `, + }); + + let na = 10.12345; + let nb = na + 0.03257; + let nc = nb + 0.03257; + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n1a"].stateValues.text).eq( + String(Math.round(na * 10 ** 8) / 10 ** 8), + ); + expect(stateVariables["/n1b"].stateValues.text).eq( + String(Math.round(nb * 10 ** 8) / 10 ** 8), + ); + expect(stateVariables["/n1c"].stateValues.text).eq( + String(Math.round(nc * 10 ** 8) / 10 ** 8), + ); + expect(stateVariables["/n2a"].stateValues.text).eq( + String(Math.round(na * 10 ** 1) / 10 ** 1), + ); + expect(stateVariables["/n2b"].stateValues.text).eq( + String(Math.round(nb * 10 ** 1) / 10 ** 1), + ); + expect(stateVariables["/n2c"].stateValues.text).eq( + String(Math.round(nc * 10 ** 1) / 10 ** 1), + ); + expect(stateVariables["/n3a"].stateValues.text).eq( + String(Math.round(na * 10 ** 3) / 10 ** 3), + ); + expect(stateVariables["/n3b"].stateValues.text).eq( + String(Math.round(nb * 10 ** 3) / 10 ** 3), + ); + expect(stateVariables["/n3c"].stateValues.text).eq( + String(Math.round(nc * 10 ** 3) / 10 ** 3), + ); + expect(stateVariables["/n4a"].stateValues.text).eq("10.0"); + expect(stateVariables["/n4b"].stateValues.text).eq("11.0"); + expect(stateVariables["/n4c"].stateValues.text).eq("12.0"); + + expect(stateVariables["/n1a1"].stateValues.text).eq( + String(Math.round(na * 10 ** 8) / 10 ** 8), + ); + expect(stateVariables["/n1b1"].stateValues.text).eq( + String(Math.round(nb * 10 ** 8) / 10 ** 8), + ); + expect(stateVariables["/n1c1"].stateValues.text).eq( + String(Math.round(nc * 10 ** 8) / 10 ** 8), + ); + expect(stateVariables["/n2a1"].stateValues.text).eq( + String(Math.round(na * 10 ** 1) / 10 ** 1), + ); + expect(stateVariables["/n2b1"].stateValues.text).eq( + String(Math.round(nb * 10 ** 1) / 10 ** 1), + ); + expect(stateVariables["/n2c1"].stateValues.text).eq( + String(Math.round(nc * 10 ** 1) / 10 ** 1), + ); + expect(stateVariables["/n3a1"].stateValues.text).eq( + String(Math.round(na * 10 ** 3) / 10 ** 3), + ); + expect(stateVariables["/n3b1"].stateValues.text).eq( + String(Math.round(nb * 10 ** 3) / 10 ** 3), + ); + expect(stateVariables["/n3c1"].stateValues.text).eq( + String(Math.round(nc * 10 ** 3) / 10 ** 3), + ); + expect(stateVariables["/n4a1"].stateValues.text).eq("10.0"); + expect(stateVariables["/n4b1"].stateValues.text).eq("11.0"); + expect(stateVariables["/n4c1"].stateValues.text).eq("12.0"); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/shuffle.test.ts b/packages/doenetml-worker/src/test/tagSpecific/shuffle.test.ts new file mode 100644 index 000000000..78057180b --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/shuffle.test.ts @@ -0,0 +1,492 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { updateMathInputValue } from "../utils/actions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +describe("Shuffle tag tests", async () => { + it("consistent order for n elements for given variant", async () => { + const doenetML = ` +

m:

+

n:

+

+ +

+

$sh

+ `; + + let core = await createTestCore({ + doenetML, + requestedVariantIndex: 1, + }); + + let texts = {}; + let orders = {}; + + let m = 1, + n = 6; + + let stateVariables = await returnAllStateVariables(core); + let componentOrder = stateVariables["/sh"].stateValues.componentOrder; + + expect([...componentOrder].sort((a, b) => a - b)).eqls( + [...Array(n - m + 1).keys()].map((x) => x + m), + ); + + orders[`${m},${n}`] = componentOrder; + + let pText = componentOrder.map((x) => x + m - 1).join(", "); + expect(stateVariables["/pList"].stateValues.text).eq(pText); + expect(stateVariables["/pList2"].stateValues.text).eq(pText); + + texts[`${m},${n}`] = pText; + + // switch n to 8 + n = 8; + await updateMathInputValue({ + latex: n.toString(), + componentName: "/n", + core, + }); + + stateVariables = await returnAllStateVariables(core); + componentOrder = stateVariables["/sh"].stateValues.componentOrder; + + expect([...componentOrder].sort((a, b) => a - b)).eqls( + [...Array(n - m + 1).keys()].map((x) => x + m), + ); + + orders[`${m},${n}`] = componentOrder; + + pText = componentOrder.map((x) => x + m - 1).join(", "); + expect(stateVariables["/pList"].stateValues.text).eq(pText); + expect(stateVariables["/pList2"].stateValues.text).eq(pText); + + texts[`${m},${n}`] = pText; + + // get another list of length 6 by setting m to 3 + m = 3; + await updateMathInputValue({ + latex: m.toString(), + componentName: "/m", + core, + }); + + stateVariables = await returnAllStateVariables(core); + componentOrder = stateVariables["/sh"].stateValues.componentOrder; + + expect(componentOrder).eqls(orders[`${1},${6}`]); + + orders[`${m},${n}`] = componentOrder; + + pText = componentOrder.map((x) => x + m - 1).join(", "); + expect(stateVariables["/pList"].stateValues.text).eq(pText); + expect(stateVariables["/pList2"].stateValues.text).eq(pText); + + texts[`${m},${n}`] = pText; + + // get another list of length 8 by setting n to 10 + n = 10; + await updateMathInputValue({ + latex: n.toString(), + componentName: "/n", + core, + }); + + stateVariables = await returnAllStateVariables(core); + componentOrder = stateVariables["/sh"].stateValues.componentOrder; + + expect(componentOrder).eqls(orders[`${1},${8}`]); + + orders[`${m},${n}`] = componentOrder; + + pText = componentOrder.map((x) => x + m - 1).join(", "); + expect(stateVariables["/pList"].stateValues.text).eq(pText); + expect(stateVariables["/pList2"].stateValues.text).eq(pText); + + texts[`${m},${n}`] = pText; + + // values change with another variant + + core = await createTestCore({ + doenetML, + requestedVariantIndex: 2, + }); + + m = 1; + n = 6; + + stateVariables = await returnAllStateVariables(core); + componentOrder = stateVariables["/sh"].stateValues.componentOrder; + + expect(componentOrder).not.eqls(orders[`${m},${n}`]); + + expect([...componentOrder].sort((a, b) => a - b)).eqls( + [...Array(n - m + 1).keys()].map((x) => x + m), + ); + + orders[`${m},${n}`] = componentOrder; + + pText = componentOrder.map((x) => x + m - 1).join(", "); + expect(stateVariables["/pList"].stateValues.text).eq(pText); + expect(stateVariables["/pList2"].stateValues.text).eq(pText); + + texts[`${m},${n}`] = pText; + + // switch n to 8 + n = 8; + await updateMathInputValue({ + latex: n.toString(), + componentName: "/n", + core, + }); + + stateVariables = await returnAllStateVariables(core); + componentOrder = stateVariables["/sh"].stateValues.componentOrder; + + expect(componentOrder).not.eqls(orders[`${m},${n}`]); + + expect([...componentOrder].sort((a, b) => a - b)).eqls( + [...Array(n - m + 1).keys()].map((x) => x + m), + ); + + orders[`${m},${n}`] = componentOrder; + + pText = componentOrder.map((x) => x + m - 1).join(", "); + expect(stateVariables["/pList"].stateValues.text).eq(pText); + expect(stateVariables["/pList2"].stateValues.text).eq(pText); + + texts[`${m},${n}`] = pText; + + // get another list of length 6 by setting m to 3 + m = 3; + await updateMathInputValue({ + latex: m.toString(), + componentName: "/m", + core, + }); + + stateVariables = await returnAllStateVariables(core); + componentOrder = stateVariables["/sh"].stateValues.componentOrder; + + expect(componentOrder).eqls(orders[`${1},${6}`]); + + orders[`${m},${n}`] = componentOrder; + + pText = componentOrder.map((x) => x + m - 1).join(", "); + expect(stateVariables["/pList"].stateValues.text).eq(pText); + expect(stateVariables["/pList2"].stateValues.text).eq(pText); + + texts[`${m},${n}`] = pText; + + // get another list of length 8 by setting n to 100 + n = 10; + await updateMathInputValue({ + latex: n.toString(), + componentName: "/n", + core, + }); + + stateVariables = await returnAllStateVariables(core); + componentOrder = stateVariables["/sh"].stateValues.componentOrder; + + expect(componentOrder).eqls(orders[`${1},${8}`]); + + orders[`${m},${n}`] = componentOrder; + + pText = componentOrder.map((x) => x + m - 1).join(", "); + expect(stateVariables["/pList"].stateValues.text).eq(pText); + expect(stateVariables["/pList2"].stateValues.text).eq(pText); + + texts[`${m},${n}`] = pText; + }); + + async function test_shuffle({ + core, + options, + must_be_reordered, + replacements_all_of_type, + }: { + core; + options: string[]; + must_be_reordered: string[][]; + replacements_all_of_type?: string; + }) { + const stateVariables = await returnAllStateVariables(core); + const componentOrder: number[] = + stateVariables["/sh"].stateValues.componentOrder; + + expect([...componentOrder].sort((a, b) => a - b)).eqls( + [...Array(options.length).keys()].map((x) => x + 1), + ); + + const orderedOptions = componentOrder.map((x) => options[x - 1]); + + for (let reorder_list of must_be_reordered) { + let indices = reorder_list.map((item) => + orderedOptions.indexOf(item), + ); + expect(indices.every((v) => v !== -1)).eq(true); + expect(indices.slice(1)).not.eqls( + [...Array(indices.length - 1).keys()].map( + (x) => x + indices[0] + 1, + ), + ); + } + + const pText = orderedOptions.join(", "); + expect(stateVariables["/pList"].stateValues.text).eq(pText); + + if (replacements_all_of_type) { + let replacementTypes = stateVariables["/pList"].activeChildren.map( + (child) => stateVariables[child.componentName].componentType, + ); + + expect(replacementTypes).eqls( + Array(options.length).fill(replacements_all_of_type), + ); + } + + return orderedOptions; + } + + it("shuffle with math and mathLists", async () => { + let core = await createTestCore({ + doenetML: ` +

+ x + y + z + a b c d + q + 1 2 3 4 +

+ `, + }); + + let options = [ + "x", + "y", + "z", + "a", + "b", + "c", + "d", + "q", + "1", + "2", + "3", + "4", + ]; + + await test_shuffle({ + core, + options, + must_be_reordered: [ + ["a", "b", "c", "d"], + ["1", "2", "3", "4"], + ], + replacements_all_of_type: "math", + }); + }); + + it("shuffle with number and numberLists", async () => { + let core = await createTestCore({ + doenetML: ` +

+ 10 + 11 + 12 + 101 102 103 104 105 + -5 + 1 2 3 4 + -99 +

+ `, + }); + + let options = [ + "10", + "11", + "12", + "101", + "102", + "103", + "104", + "105", + "-5", + "1", + "2", + "3", + "4", + "-99", + ]; + + await test_shuffle({ + core, + options, + must_be_reordered: [ + ["1", "2", "3", "4"], + ["101", "102", "103", "104"], + ], + replacements_all_of_type: "number", + }); + }); + + it("shuffle with text and textLists", async () => { + let core = await createTestCore({ + doenetML: ` +

+ apple + banana + orange + hello there now then too + almost + 1 2 3 4 + above +

+ `, + }); + + let options = [ + "apple", + "banana", + "orange", + "hello", + "there", + "now", + "then", + "too", + "almost", + "1", + "2", + "3", + "4", + "above", + ]; + + await test_shuffle({ + core, + options, + must_be_reordered: [ + ["1", "2", "3", "4"], + ["hello", "there", "now", "then", "too"], + ], + replacements_all_of_type: "text", + }); + }); + + it("shuffle sugar type math", async () => { + let core = await createTestCore({ + doenetML: ` +

+ a b c x y z +

+ `, + }); + + let options = ["a", "b", "c", "x", "y", "z"]; + + await test_shuffle({ + core, + options, + must_be_reordered: [["a", "b", "c", "x"]], + replacements_all_of_type: "math", + }); + }); + + it("shuffle sugar type number", async () => { + let core = await createTestCore({ + doenetML: ` +

+ 101 542 817 527 51 234 801 +

+ `, + }); + + let options = ["101", "542", "817", "527", "51", "234", "801"]; + + await test_shuffle({ + core, + options, + must_be_reordered: [["817", "527", "51", "234"]], + replacements_all_of_type: "number", + }); + }); + + it("shuffle sugar type text", async () => { + let core = await createTestCore({ + doenetML: ` +

+ apple + banana + orange + almost + above +

+ `, + }); + + let options = ["apple", "banana", "orange", "almost", "above"]; + + await test_shuffle({ + core, + options, + must_be_reordered: [["banana", "orange", "almost", "above"]], + replacements_all_of_type: "text", + }); + }); + + it("asList", async () => { + let core = await createTestCore({ + doenetML: ` +

+ a b c x y z +

+

+ `, + }); + + let options = ["a", "b", "c", "x", "y", "z"]; + + let orderedOptions = await test_shuffle({ + core, + options, + must_be_reordered: [], + }); + + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/pList"].stateValues.text).eq( + orderedOptions.join(", "), + ); + expect(stateVariables["/pNoList"].stateValues.text).eq( + orderedOptions.join(""), + ); + }); + + it("assignNames", async () => { + let core = await createTestCore({ + doenetML: ` + + x + y + z + a b c d + q + 1 2 3 4 + + `, + }); + + let options = ["x", "y", "z", "a", "b", "c", "d", "q", 1, 2, 3, 4]; + + const stateVariables = await returnAllStateVariables(core); + + expect( + [...Array(12).keys()] + .map((v) => stateVariables[`/x${v + 1}`].stateValues.value.tree) + .sort(), + ).eqls(options.sort()); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/sort.test.ts b/packages/doenetml-worker/src/test/tagSpecific/sort.test.ts new file mode 100644 index 000000000..5a95ceede --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/sort.test.ts @@ -0,0 +1,734 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { updateMathInputValue } from "../utils/actions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +describe("Sort tag tests", async () => { + async function test_sort({ + core, + sorted_result, + pName = "/pList", + replacements_all_of_type, + }: { + core; + sorted_result: string[]; + pName?: string; + replacements_all_of_type?: string; + }) { + const stateVariables = await returnAllStateVariables(core); + + const pText = sorted_result.join(", "); + expect(stateVariables[pName].stateValues.text).eq(pText); + + if (replacements_all_of_type) { + let replacementTypes = stateVariables[pName].activeChildren.map( + (child) => stateVariables[child.componentName].componentType, + ); + + expect(replacementTypes).eqls( + Array(sorted_result.length).fill(replacements_all_of_type), + ); + } + } + + it("sort numbers and math", async () => { + let core = await createTestCore({ + doenetML: ` +

+ 3 + pi + 1 + e + sqrt(2) + sqrt(3) + -3 10 2 + log(2) 1/e sin(2) -2/3 +

+ `, + }); + + const sorted_result = [ + "-3", + "-2/3", + "1/e", + "log(2)", + "sin(2)", + "1", + "1.4142", + "sqrt(3)", + "2", + "e", + "3", + "π", + "10", + ]; + + await test_sort({ core, sorted_result }); + }); + + it("sort dynamic maths", async () => { + let core = await createTestCore({ + doenetML: ` +

Values to sort: + + + + +

+

+ $m1$m2$m3 + $m4 + 70 + -pi +

+ `, + }); + + let sorted_result = ["-∞", "-π", "5/6", "sqrt(2)", "70", "∞"]; + + await test_sort({ core, sorted_result }); + + // change first value + await updateMathInputValue({ latex: "-5", componentName: "/m1", core }); + + sorted_result = ["-∞", "-5", "-π", "5/6", "70", "∞"]; + await test_sort({ core, sorted_result }); + + // change second value + await updateMathInputValue({ + latex: "e^5", + componentName: "/m2", + core, + }); + + sorted_result = ["-∞", "-5", "-π", "70", "e⁵", "∞"]; + await test_sort({ core, sorted_result }); + + // change third value + await updateMathInputValue({ + latex: "-100", + componentName: "/m3", + core, + }); + + sorted_result = ["-∞", "-100", "-5", "-π", "70", "e⁵"]; + await test_sort({ core, sorted_result }); + + // change fourth value + await updateMathInputValue({ + latex: "0", + componentName: "/m4", + core, + }); + + sorted_result = ["-100", "-5", "-π", "0", "70", "e⁵"]; + await test_sort({ core, sorted_result }); + }); + + it("sort nested lists of numbers and math", async () => { + let core = await createTestCore({ + doenetML: ` +

+ + + + sqrt(2)10 + + 2 + 3 + + -3 + + + sqrt(3) 1/e + + e pi + + log(2) 1 + + sin(2) -2/3 + + + + +

+ `, + }); + + const sorted_result = [ + "-3", + "-2/3", + "1/e", + "log(2)", + "sin(2)", + "1", + "1.4142", + "sqrt(3)", + "2", + "e", + "3", + "π", + "10", + ]; + + await test_sort({ core, sorted_result }); + }); + + it("sort points", async () => { + let core = await createTestCore({ + doenetML: ` + (0,1) + (-2,1) + (7,1) + (3,1) + (5,1) + +

$A$B$C$D$E

+ `, + }); + + let sorted_result = [ + "( -2, 1 )", + "( 0, 1 )", + "( 3, 1 )", + "( 5, 1 )", + "( 7, 1 )", + ]; + + await test_sort({ core, sorted_result }); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/A", + args: { x: -8, y: 9 }, + event: null, + }); + + sorted_result = [ + "( -8, 9 )", + "( -2, 1 )", + "( 3, 1 )", + "( 5, 1 )", + "( 7, 1 )", + ]; + + await test_sort({ core, sorted_result }); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/B", + args: { x: 8, y: -3 }, + event: null, + }); + + sorted_result = [ + "( -8, 9 )", + "( 3, 1 )", + "( 5, 1 )", + "( 7, 1 )", + "( 8, -3 )", + ]; + + await test_sort({ core, sorted_result }); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/C", + args: { x: 4, y: 5 }, + event: null, + }); + + sorted_result = [ + "( -8, 9 )", + "( 3, 1 )", + "( 4, 5 )", + "( 5, 1 )", + "( 8, -3 )", + ]; + + await test_sort({ core, sorted_result }); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/D", + args: { x: -9, y: 0 }, + event: null, + }); + + sorted_result = [ + "( -9, 0 )", + "( -8, 9 )", + "( 4, 5 )", + "( 5, 1 )", + "( 8, -3 )", + ]; + + await test_sort({ core, sorted_result }); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/E", + args: { x: -2, y: -1 }, + event: null, + }); + + sorted_result = [ + "( -9, 0 )", + "( -8, 9 )", + "( -2, -1 )", + "( 4, 5 )", + "( 8, -3 )", + ]; + + await test_sort({ core, sorted_result }); + }); + + it("sort points by component", async () => { + let core = await createTestCore({ + doenetML: ` + (0,5) + (-2,6) + (7,-3) + (3,2) + (5,1) + +

$A$B$C$D$E

+

$A$B$C$D$E

+

$A$B$C$D$E

+

$A$B$C$D$E

+ `, + }); + + let sorted_result_c1 = [ + "( -2, 6 )", + "( 0, 5 )", + "( 3, 2 )", + "( 5, 1 )", + "( 7, -3 )", + ]; + + await test_sort({ + core, + sorted_result: sorted_result_c1, + pName: "/pDefault", + }); + + await test_sort({ + core, + sorted_result: sorted_result_c1, + pName: "/pC1", + }); + + let sorted_result_c2 = [ + "( 7, -3 )", + "( 5, 1 )", + "( 3, 2 )", + "( 0, 5 )", + "( -2, 6 )", + ]; + + await test_sort({ + core, + sorted_result: sorted_result_c2, + pName: "/pC2", + }); + + let unsorted_results = [ + "( 0, 5 )", + "( -2, 6 )", + "( 7, -3 )", + "( 3, 2 )", + "( 5, 1 )", + ]; + await test_sort({ + core, + sorted_result: unsorted_results, + pName: "/pC3", + }); + }); + + it("sort vectors", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + +

$A$B$C$D$E

+

$A$B$C$D$E

+

$A$B$C$D$E

+ +

$A$B$C$D$E

+

$A$B$C$D$E

+

$A$B$C$D$E

+ +

$A$B$C$D$E

+

$A$B$C$D$E

+

$A$B$C$D$E

+ +

$A$B$C$D$E

+

$A$B$C$D$E

+

$A$B$C$D$E

+ `, + }); + + let sorted_result_c1d = [ + "( -2, 6 )", + "( 0, 5 )", + "( 3, 2 )", + "( 5, 1 )", + "( 7, -3 )", + ]; + + await test_sort({ + core, + sorted_result: sorted_result_c1d, + pName: "/pDefault", + }); + await test_sort({ + core, + sorted_result: sorted_result_c1d, + pName: "/pD", + }); + await test_sort({ + core, + sorted_result: sorted_result_c1d, + pName: "/pC1Default", + }); + await test_sort({ + core, + sorted_result: sorted_result_c1d, + pName: "/pC1D", + }); + + let sorted_result_c2d = [ + "( 7, -3 )", + "( 5, 1 )", + "( 3, 2 )", + "( 0, 5 )", + "( -2, 6 )", + ]; + + await test_sort({ + core, + sorted_result: sorted_result_c2d, + pName: "/pC2Default", + }); + await test_sort({ + core, + sorted_result: sorted_result_c2d, + pName: "/pC2D", + }); + + let sorted_result_c1t = [ + "( 7, -3 )", + "( 5, 1 )", + "( 3, 2 )", + "( -2, 6 )", + "( 0, 5 )", + ]; + + await test_sort({ + core, + sorted_result: sorted_result_c1t, + pName: "/pT", + }); + await test_sort({ + core, + sorted_result: sorted_result_c1t, + pName: "/pC1T", + }); + + let sorted_result_c2t = [ + "( 5, 1 )", + "( 0, 5 )", + "( 7, -3 )", + "( 3, 2 )", + "( -2, 6 )", + ]; + + await test_sort({ + core, + sorted_result: sorted_result_c2t, + pName: "/pC2T", + }); + + let unsorted_results = [ + "( 0, 5 )", + "( -2, 6 )", + "( 7, -3 )", + "( 3, 2 )", + "( 5, 1 )", + ]; + await test_sort({ + core, + sorted_result: unsorted_results, + pName: "/pC3Default", + }); + await test_sort({ + core, + sorted_result: unsorted_results, + pName: "/pC3D", + }); + await test_sort({ + core, + sorted_result: unsorted_results, + pName: "/pC3T", + }); + }); + + it("sort by prop", async () => { + let core = await createTestCore({ + doenetML: ` + + +

Coords for last point:

+

+ (a,b) + x + + + +

+ `, + }); + + let sorted_result = [ + "x", + "\uff3f", + "( a, b )", + "( x, y, z )", + "( s, t, u, v )", + ]; + + await test_sort({ core, sorted_result }); + + await updateMathInputValue({ + latex: "(a,b,c,d)", + componentName: "/cs", + core, + }); + + sorted_result = [ + "x", + "( a, b )", + "( x, y, z )", + "( s, t, u, v )", + "( a, b, c, d )", + ]; + await test_sort({ core, sorted_result }); + + await updateMathInputValue({ + latex: "(3,4,5)", + componentName: "/cs", + core, + }); + + sorted_result = [ + "x", + "( a, b )", + "( x, y, z )", + "( 3, 4, 5 )", + "( s, t, u, v )", + ]; + await test_sort({ core, sorted_result }); + }); + + it("sort texts", async () => { + let core = await createTestCore({ + doenetML: ` +

+ banana + apple + pear + grape cherry kiwi + strawberry + mango + passion fruit + orange boysenberry fig currant +

+ `, + }); + + const sorted_result = [ + "apple", + "banana", + "boysenberry", + "cherry", + "currant", + "fig", + "grape", + "kiwi", + "mango", + "orange", + "passion fruit", + "pear", + "strawberry", + ]; + + await test_sort({ + core, + sorted_result, + replacements_all_of_type: "text", + }); + }); + + it("sort texts, numbers, maths", async () => { + let core = await createTestCore({ + doenetML: ` +

+ b + 3 + 5 + 1 z 15 orange + x + 222 + 8 u + 99 765 +

+ `, + }); + + const sorted_result = [ + "1", + "15", + "222", + "3", + "5", + "765", + "8", + "99", + "b", + "orange", + "u", + "x", + "z", + ]; + + await test_sort({ + core, + sorted_result, + }); + }); + + it("sort sugar type math", async () => { + let core = await createTestCore({ + doenetML: ` +

+ z b a x y c +

+ `, + }); + + const sorted_result = ["a", "b", "c", "x", "y", "z"]; + + await test_sort({ + core, + sorted_result, + replacements_all_of_type: "math", + }); + }); + + it("sort sugar type number", async () => { + let core = await createTestCore({ + doenetML: ` +

+ 101 542 817 527 51 234 801 +

+ `, + }); + + const sorted_result = ["51", "101", "234", "527", "542", "801", "817"]; + + await test_sort({ + core, + sorted_result, + replacements_all_of_type: "number", + }); + }); + + it("sort sugar type text", async () => { + let core = await createTestCore({ + doenetML: ` +

+ orange + apple + banana + almost + above +

+ `, + }); + + const sorted_result = ["above", "almost", "apple", "banana", "orange"]; + + await test_sort({ + core, + sorted_result, + replacements_all_of_type: "text", + }); + }); + + it("asList", async () => { + let core = await createTestCore({ + doenetML: ` +

+ z b a x y c +

+

+ `, + }); + + const sorted_result = ["a", "b", "c", "x", "y", "z"]; + + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/pList"].stateValues.text).eq( + sorted_result.join(", "), + ); + expect(stateVariables["/pNoList"].stateValues.text).eq( + sorted_result.join(""), + ); + }); + + it("assignNames", async () => { + let core = await createTestCore({ + doenetML: ` + + y + x + a d c b + z + 2 3 1 4 + q + + `, + }); + + let sorted_result = [ + 1, + 2, + 3, + 4, + "a", + "b", + "c", + "d", + "q", + "x", + "y", + "z", + ]; + + const stateVariables = await returnAllStateVariables(core); + + expect( + [...Array(12).keys()] + .map((v) => stateVariables[`/x${v + 1}`].stateValues.value.tree) + .sort(), + ).eqls(sorted_result.sort()); + }); +}); 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/doenetml-worker/src/test/tagSpecific/text.test.ts b/packages/doenetml-worker/src/test/tagSpecific/text.test.ts index 88174cb86..b77f783b3 100644 --- a/packages/doenetml-worker/src/test/tagSpecific/text.test.ts +++ b/packages/doenetml-worker/src/test/tagSpecific/text.test.ts @@ -209,7 +209,6 @@ describe("Text tag tests", async () => {

FixLocation 2: $fixLocation2

Change fixLocation 1

Change fixLocation 2

-

`, }); diff --git a/packages/doenetml-worker/src/test/tagSpecific/textinput.test.ts b/packages/doenetml-worker/src/test/tagSpecific/textinput.test.ts new file mode 100644 index 000000000..2f81e6ab0 --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/textinput.test.ts @@ -0,0 +1,1577 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { cleanLatex } from "../utils/math"; +import { + updateBooleanInputValue, + updateMathInputValue, + updateTextInputImmediateValue, + updateTextInputValue, + updateTextInputValueToImmediateValue, +} from "../utils/actions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +describe("TextInput tag tests", async () => { + it("textInput references", async () => { + // A fairly involved test + // to check for bugs that have shown up only after multiple manipulations + + // Initial doenet code + + let core = await createTestCore({ + doenetML: ` + + + $ti1.value{assignNames="v1"} + $ti1.immediateValue{assignNames="iv1"} + $ti1a.value{assignNames="v1a"} + $ti1a.immediateValue{assignNames="iv1a"} + + $ti2.value{assignNames="v2"} + $ti2.immediateValue{assignNames="iv2"} + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq("hello"); + expect(stateVariables["/ti1a"].stateValues.immediateValue).eq("hello"); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq(""); + expect(stateVariables["/ti1"].stateValues.value).eq("hello"); + expect(stateVariables["/ti1a"].stateValues.value).eq("hello"); + expect(stateVariables["/ti2"].stateValues.value).eq(""); + + // Type 2 in first textInput + await updateTextInputImmediateValue({ + text: "hello2", + componentName: "/ti1", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq("hello2"); + expect(stateVariables["/ti1a"].stateValues.immediateValue).eq("hello2"); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq(""); + expect(stateVariables["/ti1"].stateValues.value).eq("hello"); + expect(stateVariables["/ti1a"].stateValues.value).eq("hello"); + expect(stateVariables["/ti2"].stateValues.value).eq(""); + + // Update value (e.g., by pressing Enter) in first textInput + await updateTextInputValueToImmediateValue({ + componentName: "/ti1", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq("hello2"); + expect(stateVariables["/ti1a"].stateValues.immediateValue).eq("hello2"); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq(""); + expect(stateVariables["/ti1"].stateValues.value).eq("hello2"); + expect(stateVariables["/ti1a"].stateValues.value).eq("hello2"); + expect(stateVariables["/ti2"].stateValues.value).eq(""); + + // erase "2" and type " you" in second input + + await updateTextInputImmediateValue({ + text: "hello", + componentName: "/ti1a", + core, + }); + await updateTextInputImmediateValue({ + text: "hello you", + componentName: "/ti1a", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq( + "hello you", + ); + expect(stateVariables["/ti1a"].stateValues.immediateValue).eq( + "hello you", + ); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq(""); + expect(stateVariables["/ti1"].stateValues.value).eq("hello2"); + expect(stateVariables["/ti1a"].stateValues.value).eq("hello2"); + expect(stateVariables["/ti2"].stateValues.value).eq(""); + + // Update value (e.g., by changing focus) of second textInput + await updateTextInputValueToImmediateValue({ + componentName: "/ti1a", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq( + "hello you", + ); + expect(stateVariables["/ti1a"].stateValues.immediateValue).eq( + "hello you", + ); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq(""); + expect(stateVariables["/ti1"].stateValues.value).eq("hello you"); + expect(stateVariables["/ti1a"].stateValues.value).eq("hello you"); + expect(stateVariables["/ti2"].stateValues.value).eq(""); + + // bye in third input + await updateTextInputImmediateValue({ + text: "bye", + componentName: "/ti2", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq( + "hello you", + ); + expect(stateVariables["/ti1a"].stateValues.immediateValue).eq( + "hello you", + ); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq("bye"); + expect(stateVariables["/ti1"].stateValues.value).eq("hello you"); + expect(stateVariables["/ti1a"].stateValues.value).eq("hello you"); + expect(stateVariables["/ti2"].stateValues.value).eq(""); + + // update value (e.g., press enter) in third textInput + await updateTextInputValueToImmediateValue({ + componentName: "/ti2", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq( + "hello you", + ); + expect(stateVariables["/ti1a"].stateValues.immediateValue).eq( + "hello you", + ); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq("bye"); + expect(stateVariables["/ti1"].stateValues.value).eq("hello you"); + expect(stateVariables["/ti1a"].stateValues.value).eq("hello you"); + expect(stateVariables["/ti2"].stateValues.value).eq("bye"); + + // Type abc in second textInput + await updateTextInputImmediateValue({ + text: "abc", + componentName: "/ti1a", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq("abc"); + expect(stateVariables["/ti1a"].stateValues.immediateValue).eq("abc"); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq("bye"); + expect(stateVariables["/ti1"].stateValues.value).eq("hello you"); + expect(stateVariables["/ti1a"].stateValues.value).eq("hello you"); + expect(stateVariables["/ti2"].stateValues.value).eq("bye"); + + // update value (e.g., blur) textInput 2 + await updateTextInputValueToImmediateValue({ + componentName: "/ti1a", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq("abc"); + expect(stateVariables["/ti1a"].stateValues.immediateValue).eq("abc"); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq("bye"); + expect(stateVariables["/ti1"].stateValues.value).eq("abc"); + expect(stateVariables["/ti1a"].stateValues.value).eq("abc"); + expect(stateVariables["/ti2"].stateValues.value).eq("bye"); + + // delete and reenter abc in mathInput 1 + + await updateTextInputImmediateValue({ + text: "", + componentName: "/ti1", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq(""); + + await updateTextInputImmediateValue({ + text: "a", + componentName: "/ti1", + core, + }); + await updateTextInputImmediateValue({ + text: "ab", + componentName: "/ti1", + core, + }); + await updateTextInputImmediateValue({ + text: "abc", + componentName: "/ti1", + core, + }); + await updateTextInputValueToImmediateValue({ + componentName: "/ti1", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq("abc"); + expect(stateVariables["/ti1a"].stateValues.immediateValue).eq("abc"); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq("bye"); + expect(stateVariables["/ti1"].stateValues.value).eq("abc"); + expect(stateVariables["/ti1a"].stateValues.value).eq("abc"); + expect(stateVariables["/ti2"].stateValues.value).eq("bye"); + + // type saludos in textInput 3 + + await updateTextInputImmediateValue({ + text: "saludos", + componentName: "/ti2", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq("abc"); + expect(stateVariables["/ti1a"].stateValues.immediateValue).eq("abc"); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq("saludos"); + expect(stateVariables["/ti1"].stateValues.value).eq("abc"); + expect(stateVariables["/ti1a"].stateValues.value).eq("abc"); + expect(stateVariables["/ti2"].stateValues.value).eq("bye"); + + // blur textInput 2 and type d in textInput 1 + await updateTextInputValueToImmediateValue({ + componentName: "/ti2", + core, + }); + await updateTextInputImmediateValue({ + text: "abcd", + componentName: "/ti1", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq("abcd"); + expect(stateVariables["/ti1a"].stateValues.immediateValue).eq("abcd"); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq("saludos"); + expect(stateVariables["/ti1"].stateValues.value).eq("abc"); + expect(stateVariables["/ti1a"].stateValues.value).eq("abc"); + expect(stateVariables["/ti2"].stateValues.value).eq("saludos"); + + // Update value (e.g., blur) of first textInput + await updateTextInputValueToImmediateValue({ + componentName: "/ti1", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq("abcd"); + expect(stateVariables["/ti1a"].stateValues.immediateValue).eq("abcd"); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq("saludos"); + expect(stateVariables["/ti1"].stateValues.value).eq("abcd"); + expect(stateVariables["/ti1a"].stateValues.value).eq("abcd"); + expect(stateVariables["/ti2"].stateValues.value).eq("saludos"); + + // Clearing second textInput + await updateTextInputImmediateValue({ + text: "", + componentName: "/ti1a", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq(""); + expect(stateVariables["/ti1a"].stateValues.immediateValue).eq(""); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq("saludos"); + expect(stateVariables["/ti1"].stateValues.value).eq("abcd"); + expect(stateVariables["/ti1a"].stateValues.value).eq("abcd"); + expect(stateVariables["/ti2"].stateValues.value).eq("saludos"); + + // update value (e.g., by blurring) of second textInput + await updateTextInputValueToImmediateValue({ + componentName: "/ti1a", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq(""); + expect(stateVariables["/ti1a"].stateValues.immediateValue).eq(""); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq("saludos"); + expect(stateVariables["/ti1"].stateValues.value).eq(""); + expect(stateVariables["/ti1a"].stateValues.value).eq(""); + expect(stateVariables["/ti2"].stateValues.value).eq("saludos"); + }); + + it("downstream from textInput", async () => { + let core = await createTestCore({ + doenetML: ` +

Original text: hello there

+

textInput based on text:

+

Copied textInput:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.value).eq("hello there"); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq( + "hello there", + ); + expect(stateVariables["/t1"].stateValues.value).eq("hello there"); + expect(stateVariables["/ti2"].stateValues.value).eq("hello there"); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq( + "hello there", + ); + + // enter new values + await updateTextInputValue({ + text: "bye now", + componentName: "/ti1", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.value).eq("bye now"); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq("bye now"); + expect(stateVariables["/t1"].stateValues.value).eq("bye now"); + expect(stateVariables["/ti2"].stateValues.value).eq("bye now"); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq("bye now"); + }); + + it("downstream from textInput prefill ignored", async () => { + let core = await createTestCore({ + doenetML: ` +

Original text: hello there

+

textInput based on text:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.value).eq("hello there"); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq( + "hello there", + ); + expect(stateVariables["/t1"].stateValues.value).eq("hello there"); + }); + + it("downstream from textInput, values revert if not updatable", async () => { + let core = await createTestCore({ + doenetML: ` +

Original text: can't update me

+

textInput based on text:

+

immediate value: $ti1.immediateValue{assignNames="iv"}

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.value).eq(`can't update me`); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq( + `can't update me`, + ); + expect(stateVariables["/t1"].stateValues.value).eq(`can't update me`); + + // enter new values + await updateTextInputImmediateValue({ + text: "disappear", + componentName: "/ti1", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.value).eq(`can't update me`); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq( + `disappear`, + ); + expect(stateVariables["/t1"].stateValues.value).eq(`can't update me`); + + // values revert when press update value + await updateTextInputValueToImmediateValue({ + componentName: "/ti1", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.value).eq(`can't update me`); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq( + `can't update me`, + ); + expect(stateVariables["/t1"].stateValues.value).eq(`can't update me`); + }); + + it("downstream from textInput via child", async () => { + let core = await createTestCore({ + doenetML: ` +

Original text: hello there

+

textInput based on text: $t1

+

Copied textInput:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.value).eq("hello there"); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq( + "hello there", + ); + expect(stateVariables["/t1"].stateValues.value).eq("hello there"); + expect(stateVariables["/ti2"].stateValues.value).eq("hello there"); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq( + "hello there", + ); + + // enter new values + await updateTextInputValue({ + text: "bye now", + componentName: "/ti1", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.value).eq("bye now"); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq("bye now"); + expect(stateVariables["/t1"].stateValues.value).eq("bye now"); + expect(stateVariables["/ti2"].stateValues.value).eq("bye now"); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq("bye now"); + }); + + it("downstream from textInput prefill ignored, via child", async () => { + let core = await createTestCore({ + doenetML: ` +

Original text: hello there

+

textInput based on text: $t1

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.value).eq("hello there"); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq( + "hello there", + ); + expect(stateVariables["/t1"].stateValues.value).eq("hello there"); + }); + + it("downstream from textInput via child, values revert if not updatable", async () => { + let core = await createTestCore({ + doenetML: ` +

Original text: can't update me

+

textInput based on text: $t1

+

immediate value: $ti1.immediateValue{assignNames="iv"}

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.value).eq(`can't update me`); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq( + `can't update me`, + ); + expect(stateVariables["/t1"].stateValues.value).eq(`can't update me`); + + // enter new values + await updateTextInputImmediateValue({ + text: "disappear", + componentName: "/ti1", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.value).eq(`can't update me`); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq( + `disappear`, + ); + expect(stateVariables["/t1"].stateValues.value).eq(`can't update me`); + + // values revert when press update value + await updateTextInputValueToImmediateValue({ + componentName: "/ti1", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.value).eq(`can't update me`); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq( + `can't update me`, + ); + expect(stateVariables["/t1"].stateValues.value).eq(`can't update me`); + }); + + it("downstream from textInput via child, bindValueTo ignored", async () => { + let core = await createTestCore({ + doenetML: ` +

Original text: hello there

+

Not bound: ignore me

+

textInput based on text: $t1

+

Copied textInput:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.value).eq("hello there"); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq( + "hello there", + ); + expect(stateVariables["/t1"].stateValues.value).eq("hello there"); + expect(stateVariables["/ti2"].stateValues.value).eq("hello there"); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq( + "hello there", + ); + expect(stateVariables["/tIgnored"].stateValues.value).eq("ignore me"); + + // enter new values + await updateTextInputValue({ + text: "bye now", + componentName: "/ti1", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.value).eq("bye now"); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq("bye now"); + expect(stateVariables["/t1"].stateValues.value).eq("bye now"); + expect(stateVariables["/ti2"].stateValues.value).eq("bye now"); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq("bye now"); + expect(stateVariables["/tIgnored"].stateValues.value).eq("ignore me"); + }); + + it("textInput based on value of textInput", async () => { + let core = await createTestCore({ + doenetML: ` +

Original textInput:

+

textInput based on textInput:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq( + "hello there", + ); + expect(stateVariables["/ti1"].stateValues.value).eq("hello there"); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq( + "hello there", + ); + expect(stateVariables["/ti2"].stateValues.value).eq("hello there"); + + // type new values in first textInput + await updateTextInputImmediateValue({ + text: "bye now", + componentName: "/ti1", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq("bye now"); + expect(stateVariables["/ti1"].stateValues.value).eq("hello there"); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq( + "hello there", + ); + expect(stateVariables["/ti2"].stateValues.value).eq("hello there"); + + // update value + await updateTextInputValueToImmediateValue({ + componentName: "/ti1", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq("bye now"); + expect(stateVariables["/ti1"].stateValues.value).eq("bye now"); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq("bye now"); + expect(stateVariables["/ti2"].stateValues.value).eq("bye now"); + + // type values input second textInput + await updateTextInputImmediateValue({ + text: "Hello again", + componentName: "/ti2", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq("bye now"); + expect(stateVariables["/ti1"].stateValues.value).eq("bye now"); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq( + "Hello again", + ); + expect(stateVariables["/ti2"].stateValues.value).eq("bye now"); + + // update value of second textInput + await updateTextInputValueToImmediateValue({ + componentName: "/ti2", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq( + "Hello again", + ); + expect(stateVariables["/ti1"].stateValues.value).eq("Hello again"); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq( + "Hello again", + ); + expect(stateVariables["/ti2"].stateValues.value).eq("Hello again"); + }); + + it("textInput based on immediateValue of textInput", async () => { + let core = await createTestCore({ + doenetML: ` +

Original textInput:

+

textInput based on textInput:

+ `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq( + "hello there", + ); + expect(stateVariables["/ti1"].stateValues.value).eq("hello there"); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq( + "hello there", + ); + expect(stateVariables["/ti2"].stateValues.value).eq("hello there"); + + // type new values in first textInput + await updateTextInputImmediateValue({ + text: "bye now", + componentName: "/ti1", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq("bye now"); + expect(stateVariables["/ti1"].stateValues.value).eq("hello there"); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq("bye now"); + expect(stateVariables["/ti2"].stateValues.value).eq("bye now"); + + // update value + await updateTextInputValueToImmediateValue({ + componentName: "/ti1", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq("bye now"); + expect(stateVariables["/ti1"].stateValues.value).eq("bye now"); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq("bye now"); + expect(stateVariables["/ti2"].stateValues.value).eq("bye now"); + + // type values input second textInput + await updateTextInputImmediateValue({ + text: "Hello again", + componentName: "/ti2", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq("bye now"); + expect(stateVariables["/ti1"].stateValues.value).eq("bye now"); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq( + "Hello again", + ); + expect(stateVariables["/ti2"].stateValues.value).eq("bye now"); + + // update value of second textInput + await updateTextInputValueToImmediateValue({ + componentName: "/ti2", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.immediateValue).eq( + "Hello again", + ); + expect(stateVariables["/ti1"].stateValues.value).eq("Hello again"); + expect(stateVariables["/ti2"].stateValues.immediateValue).eq( + "Hello again", + ); + expect(stateVariables["/ti2"].stateValues.value).eq("Hello again"); + }); + + it("chain update off textInput", async () => { + let core = await createTestCore({ + doenetML: ` + + + hello + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/h"].stateValues.value).eq("hello"); + + await updateTextInputImmediateValue({ + text: " bye", + componentName: "/ti", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti"].stateValues.immediateValue).eq(" bye"); + expect(stateVariables["/h"].stateValues.value).eq("hello"); + + await updateTextInputImmediateValue({ + text: " there", + componentName: "/ti", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti"].stateValues.immediateValue).eq(" there"); + expect(stateVariables["/h"].stateValues.value).eq("hello"); + + await updateTextInputValueToImmediateValue({ + componentName: "/ti", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti"].stateValues.immediateValue).eq(" there"); + expect(stateVariables["/h"].stateValues.value).eq("hello there"); + + await updateTextInputImmediateValue({ + text: "?", + componentName: "/ti", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti"].stateValues.immediateValue).eq("?"); + expect(stateVariables["/h"].stateValues.value).eq("hello there"); + + await updateTextInputImmediateValue({ + text: "!", + componentName: "/ti", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti"].stateValues.immediateValue).eq("!"); + expect(stateVariables["/h"].stateValues.value).eq("hello there"); + + await updateTextInputValueToImmediateValue({ + componentName: "/ti", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti"].stateValues.immediateValue).eq("!"); + expect(stateVariables["/h"].stateValues.value).eq("hello there!"); + }); + + it("text input in graph", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + +

Anchor 1 coordinates:

+

Anchor 2 coordinates:

+

Change anchor 1 coordinates:

+

Change anchor 2 coordinates:

+

Position from anchor 1: $textInput1.positionFromAnchor

+

Position from anchor 2: $textInput2.positionFromAnchor

+

Change position from anchor 1 + + upperRight + upperLeft + lowerRight + lowerLeft + left + right + top + bottom + center + +

+

Change position from anchor 2 + + upperRight + upperLeft + lowerRight + lowerLeft + left + right + top + bottom + center + +

+

Draggable 1: $draggable1

+

Draggable 2: $draggable2

+

Change draggable 1

+

Change draggable 2

+

Disabled 1: $disabled1

+

Disabled 2: $disabled2

+

Change disabled 1

+

Change disabled 2

+

Fixed 1: $fixed1

+

Fixed 2: $fixed2

+

Change fixed 1

+

Change fixed 2

+

FixLocation 1: $fixLocation1

+

FixLocation 2: $fixLocation2

+

Change fixLocation 1

+

Change fixLocation 2

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/textInput1anchor"].stateValues.latex), + ).eq("(1,3)"); + expect( + cleanLatex(stateVariables["/textInput2anchor"].stateValues.latex), + ).eq("(0,0)"); + + expect(stateVariables["/pPositionFromAnchor1"].stateValues.text).eq( + "Position from anchor 1: upperright", + ); + expect(stateVariables["/pPositionFromAnchor2"].stateValues.text).eq( + "Position from anchor 2: center", + ); + expect( + stateVariables["/positionFromAnchor1"].stateValues.selectedIndices, + ).eqls([1]); + expect( + stateVariables["/positionFromAnchor2"].stateValues.selectedIndices, + ).eqls([9]); + + expect(stateVariables["/pDraggable1"].stateValues.text).eq( + "Draggable 1: true", + ); + expect(stateVariables["/pDraggable2"].stateValues.text).eq( + "Draggable 2: true", + ); + expect(stateVariables["/pDisabled1"].stateValues.text).eq( + "Disabled 1: true", + ); + expect(stateVariables["/pDisabled2"].stateValues.text).eq( + "Disabled 2: false", + ); + expect(stateVariables["/pFixed1"].stateValues.text).eq( + "Fixed 1: false", + ); + expect(stateVariables["/pFixed2"].stateValues.text).eq( + "Fixed 2: false", + ); + expect(stateVariables["/pFixLocation1"].stateValues.text).eq( + "FixLocation 1: false", + ); + expect(stateVariables["/pFixLocation2"].stateValues.text).eq( + "FixLocation 2: false", + ); + + // move textInputs by dragging + await core.requestAction({ + actionName: "moveInput", + componentName: "/textInput1", + args: { x: -2, y: 3 }, + event: null, + }); + await core.requestAction({ + actionName: "moveInput", + componentName: "/textInput2", + args: { x: 4, y: -5 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/textInput1anchor"].stateValues.latex), + ).eq("(-2,3)"); + expect( + cleanLatex(stateVariables["/textInput2anchor"].stateValues.latex), + ).eq("(4,-5)"); + + // move textInputs by entering coordinates + + await updateMathInputValue({ + latex: "(6,7)", + componentName: "/anchorCoords1", + core, + }); + await updateMathInputValue({ + latex: "(8,9)", + componentName: "/anchorCoords2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/textInput1anchor"].stateValues.latex), + ).eq("(6,7)"); + expect( + cleanLatex(stateVariables["/textInput2anchor"].stateValues.latex), + ).eq("(8,9)"); + + // change position from anchor + await core.requestAction({ + actionName: "updateSelectedIndices", + componentName: "/positionFromAnchor1", + args: { selectedIndices: [4] }, + event: null, + }); + await core.requestAction({ + actionName: "updateSelectedIndices", + componentName: "/positionFromAnchor2", + args: { selectedIndices: [3] }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pPositionFromAnchor1"].stateValues.text).eq( + "Position from anchor 1: lowerleft", + ); + expect(stateVariables["/pPositionFromAnchor2"].stateValues.text).eq( + "Position from anchor 2: lowerright", + ); + + // make not draggable + await updateBooleanInputValue({ + boolean: false, + componentName: "/draggable1", + core, + }); + await updateBooleanInputValue({ + boolean: false, + componentName: "/draggable2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pDraggable1"].stateValues.text).eq( + "Draggable 1: false", + ); + expect(stateVariables["/pDraggable2"].stateValues.text).eq( + "Draggable 2: false", + ); + + // cannot move textInputs by dragging + await core.requestAction({ + actionName: "moveInput", + componentName: "/textInput1", + args: { x: -10, y: -9 }, + event: null, + }); + await core.requestAction({ + actionName: "moveInput", + componentName: "/textInput2", + args: { x: -8, y: -7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/textInput1anchor"].stateValues.latex), + ).eq("(6,7)"); + expect( + cleanLatex(stateVariables["/textInput2anchor"].stateValues.latex), + ).eq("(8,9)"); + + // make draggable again + await updateBooleanInputValue({ + boolean: true, + componentName: "/draggable1", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/draggable2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pDraggable1"].stateValues.text).eq( + "Draggable 1: true", + ); + expect(stateVariables["/pDraggable2"].stateValues.text).eq( + "Draggable 2: true", + ); + + await core.requestAction({ + actionName: "moveInput", + componentName: "/textInput1", + args: { x: -10, y: -9 }, + event: null, + }); + await core.requestAction({ + actionName: "moveInput", + componentName: "/textInput2", + args: { x: -8, y: -7 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/textInput1anchor"].stateValues.latex), + ).eq("(-10,-9)"); + expect( + cleanLatex(stateVariables["/textInput2anchor"].stateValues.latex), + ).eq("(-8,-7)"); + + // fix location + await updateBooleanInputValue({ + boolean: true, + componentName: "/fixLocation1", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/fixLocation2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pFixLocation1"].stateValues.text).eq( + "FixLocation 1: true", + ); + expect(stateVariables["/pFixLocation2"].stateValues.text).eq( + "FixLocation 2: true", + ); + + // can change coordinates entering coordinates only for input 1 + await updateMathInputValue({ + latex: "(3,4)", + componentName: "/anchorCoords2", + core, + }); + await updateMathInputValue({ + latex: "(1,2)", + componentName: "/anchorCoords1", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/textInput1anchor"].stateValues.latex), + ).eq("(1,2)"); + expect( + cleanLatex(stateVariables["/textInput2anchor"].stateValues.latex), + ).eq("(-8,-7)"); + + // cannot move textInputs by dragging + await core.requestAction({ + actionName: "moveInput", + componentName: "/textInput1", + args: { x: 4, y: 6 }, + event: null, + }); + await core.requestAction({ + actionName: "moveInput", + componentName: "/textInput2", + args: { x: 7, y: 8 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/textInput1anchor"].stateValues.latex), + ).eq("(1,2)"); + expect( + cleanLatex(stateVariables["/textInput2anchor"].stateValues.latex), + ).eq("(-8,-7)"); + + // can change position from anchor only for input 1 + await core.requestAction({ + actionName: "updateSelectedIndices", + componentName: "/positionFromAnchor2", + args: { selectedIndices: [8] }, + event: null, + }); + await core.requestAction({ + actionName: "updateSelectedIndices", + componentName: "/positionFromAnchor1", + args: { selectedIndices: [7] }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pPositionFromAnchor1"].stateValues.text).eq( + "Position from anchor 1: top", + ); + expect(stateVariables["/pPositionFromAnchor2"].stateValues.text).eq( + "Position from anchor 2: lowerright", + ); + + // can change disabled attribute + await updateBooleanInputValue({ + boolean: false, + componentName: "/disabled1", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/disabled2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pDisabled1"].stateValues.text).eq( + "Disabled 1: false", + ); + expect(stateVariables["/pDisabled2"].stateValues.text).eq( + "Disabled 2: true", + ); + + // make completely fixed + await updateBooleanInputValue({ + boolean: true, + componentName: "/fixed1", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/fixed2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pFixed1"].stateValues.text).eq("Fixed 1: true"); + expect(stateVariables["/pFixed2"].stateValues.text).eq("Fixed 2: true"); + + // can change coordinates entering coordinates only for input 1 + await updateMathInputValue({ + latex: "(7,8)", + componentName: "/anchorCoords2", + core, + }); + await updateMathInputValue({ + latex: "(5,6)", + componentName: "/anchorCoords1", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect( + cleanLatex(stateVariables["/textInput1anchor"].stateValues.latex), + ).eq("(5,6)"); + expect( + cleanLatex(stateVariables["/textInput2anchor"].stateValues.latex), + ).eq("(-8,-7)"); + + // can change position from anchor only for math 1 + await core.requestAction({ + actionName: "updateSelectedIndices", + componentName: "/positionFromAnchor2", + args: { selectedIndices: [5] }, + event: null, + }); + await core.requestAction({ + actionName: "updateSelectedIndices", + componentName: "/positionFromAnchor1", + args: { selectedIndices: [6] }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pPositionFromAnchor1"].stateValues.text).eq( + "Position from anchor 1: right", + ); + expect(stateVariables["/pPositionFromAnchor2"].stateValues.text).eq( + "Position from anchor 2: lowerright", + ); + + // can change disabled attribute only for input 1 + + await updateBooleanInputValue({ + boolean: true, + componentName: "/disabled1", + core, + }); + await updateBooleanInputValue({ + boolean: false, + componentName: "/disabled2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pDisabled1"].stateValues.text).eq( + "Disabled 1: true", + ); + expect(stateVariables["/pDisabled2"].stateValues.text).eq( + "Disabled 2: true", + ); + }); + + it("use textInput as basic math input", async () => { + let core = await createTestCore({ + doenetML: ` + + +

Math from text input: $ti

+

Number from text input: $ti

+

Math via latex from text input: $ti.value{isLatex}

+

Number via latex from text input: $ti.value{isLatex}

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/m1"].stateValues.value.tree).eq("\uff3f"); + expect(stateVariables["/m2"].stateValues.value.tree).eq("\uff3f"); + expect(stateVariables["/n1"].stateValues.value).eqls(NaN); + expect(stateVariables["/n2"].stateValues.value).eqls(NaN); + + await updateTextInputValue({ text: "4/2", componentName: "/ti", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/m1"].stateValues.value.tree).eqls(["/", 4, 2]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls(["/", 4, 2]); + expect(stateVariables["/n1"].stateValues.value).eq(2); + expect(stateVariables["/n2"].stateValues.value).eq(2); + + await updateTextInputValue({ text: "xy", componentName: "/ti", core }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/m1"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/m2"].stateValues.value.tree).eqls([ + "*", + "x", + "y", + ]); + expect(stateVariables["/n1"].stateValues.value).eqls(NaN); + expect(stateVariables["/n2"].stateValues.value).eqls(NaN); + + await updateTextInputValue({ + text: "\\frac{a}{b}", + componentName: "/ti", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/m1"].stateValues.value.tree).eq("\uff3f"); + expect(stateVariables["/m2"].stateValues.value.tree).eqls([ + "/", + "a", + "b", + ]); + expect(stateVariables["/n1"].stateValues.value).eqls(NaN); + expect(stateVariables["/n2"].stateValues.value).eqls(NaN); + + await updateTextInputValue({ + text: "\\frac{6}{2}", + componentName: "/ti", + core, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/m1"].stateValues.value.tree).eq("\uff3f"); + expect(stateVariables["/m2"].stateValues.value.tree).eqls(["/", 6, 2]); + expect(stateVariables["/n1"].stateValues.value).eqls(NaN); + expect(stateVariables["/n2"].stateValues.value).eq(3); + }); + + it("valueChanged", async () => { + let doenetML = ` +

+

+

+

$ti2.immediateValue

+ + `; + + async function check_items( + [ti1, ti2, ti3, ti4]: [ + ti1: string, + ti2: string, + ti3: string, + ti4: string, + ], + [ti1iv, ti2iv, ti3iv, ti4iv]: [ + ti1iv: string, + ti2iv: string, + ti3iv: string, + ti4iv: string, + ], + [ti1changed, ti2changed, ti3changed, ti4changed]: [ + ti1changed: boolean, + ti2changed: boolean, + ti3changed: boolean, + ti4changed: boolean, + ], + [ti1ivchanged, ti2ivchanged, ti3ivchanged, ti4ivchanged]: [ + ti1ivchanged: boolean, + ti2ivchanged: boolean, + ti3ivchanged: boolean, + ti4ivchanged: boolean, + ], + ) { + const stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.value).eq(ti1); + expect(stateVariables["/ti2"].stateValues.value).eq(ti2); + expect(stateVariables["/ti3"].stateValues.value).eq(ti3); + expect(stateVariables["/ti4"].stateValues.value).eq(ti4); + + expect(stateVariables["/ti1a"].stateValues.value).eq(ti1); + expect(stateVariables["/ti2a"].stateValues.value).eq(ti2); + expect(stateVariables["/ti3a"].stateValues.value).eq(ti3); + expect(stateVariables["/ti4a"].stateValues.value).eq(ti4); + + expect(stateVariables["/ti1iva"].stateValues.value).eq(ti1iv); + expect(stateVariables["/ti2iva"].stateValues.value).eq(ti2iv); + expect(stateVariables["/ti3iva"].stateValues.value).eq(ti3iv); + expect(stateVariables["/ti4iva"].stateValues.value).eq(ti4iv); + + expect(stateVariables["/ti1changed"].stateValues.value).eq( + ti1changed, + ); + expect(stateVariables["/ti2changed"].stateValues.value).eq( + ti2changed, + ); + expect(stateVariables["/ti3changed"].stateValues.value).eq( + ti3changed, + ); + expect(stateVariables["/ti4changed"].stateValues.value).eq( + ti4changed, + ); + + expect(stateVariables["/ti1ivchanged"].stateValues.value).eq( + ti1ivchanged, + ); + expect(stateVariables["/ti2ivchanged"].stateValues.value).eq( + ti2ivchanged, + ); + expect(stateVariables["/ti3ivchanged"].stateValues.value).eq( + ti3ivchanged, + ); + expect(stateVariables["/ti4ivchanged"].stateValues.value).eq( + ti4ivchanged, + ); + } + + let core = await createTestCore({ + doenetML, + }); + + let ti1 = "", + ti2 = "apple", + ti3 = "", + ti4 = "apple"; + let ti1iv = "", + ti2iv = "apple", + ti3iv = "", + ti4iv = "apple"; + let ti1changed = false, + ti2changed = false, + ti3changed = false, + ti4changed = false; + let ti1ivchanged = false, + ti2ivchanged = false, + ti3ivchanged = false, + ti4ivchanged = false; + + await check_items( + [ti1, ti2, ti3, ti4], + [ti1iv, ti2iv, ti3iv, ti4iv], + [ti1changed, ti2changed, ti3changed, ti4changed], + [ti1ivchanged, ti2ivchanged, ti3ivchanged, ti4ivchanged], + ); + + // type in first marks only first immediate value as changed + ti1iv = "banana"; + ti1ivchanged = true; + await updateTextInputImmediateValue({ + text: ti1iv, + componentName: "/ti1", + core, + }); + await check_items( + [ti1, ti2, ti3, ti4], + [ti1iv, ti2iv, ti3iv, ti4iv], + [ti1changed, ti2changed, ti3changed, ti4changed], + [ti1ivchanged, ti2ivchanged, ti3ivchanged, ti4ivchanged], + ); + + // update value in first marks only first value as changed + ti1 = ti3 = ti3iv = ti1iv; + ti1changed = true; + await updateTextInputValueToImmediateValue({ + componentName: "/ti1", + core, + }); + + await check_items( + [ti1, ti2, ti3, ti4], + [ti1iv, ti2iv, ti3iv, ti4iv], + [ti1changed, ti2changed, ti3changed, ti4changed], + [ti1ivchanged, ti2ivchanged, ti3ivchanged, ti4ivchanged], + ); + + // type in second marks only second immediate value as changed + + ti4 = ti4iv = ti2iv = "cherry"; + ti2ivchanged = true; + await updateTextInputImmediateValue({ + text: ti2iv, + componentName: "/ti2", + core, + }); + await check_items( + [ti1, ti2, ti3, ti4], + [ti1iv, ti2iv, ti3iv, ti4iv], + [ti1changed, ti2changed, ti3changed, ti4changed], + [ti1ivchanged, ti2ivchanged, ti3ivchanged, ti4ivchanged], + ); + + // update value in second marks only second value as changed + ti2 = ti2iv; + ti2changed = true; + await updateTextInputValueToImmediateValue({ + componentName: "/ti2", + core, + }); + + await check_items( + [ti1, ti2, ti3, ti4], + [ti1iv, ti2iv, ti3iv, ti4iv], + [ti1changed, ti2changed, ti3changed, ti4changed], + [ti1ivchanged, ti2ivchanged, ti3ivchanged, ti4ivchanged], + ); + + // type in third marks third immediate value as changed + ti3iv = "dragonfruit"; + ti3ivchanged = true; + await updateTextInputImmediateValue({ + text: ti3iv, + componentName: "/ti3", + core, + }); + await check_items( + [ti1, ti2, ti3, ti4], + [ti1iv, ti2iv, ti3iv, ti4iv], + [ti1changed, ti2changed, ti3changed, ti4changed], + [ti1ivchanged, ti2ivchanged, ti3ivchanged, ti4ivchanged], + ); + + // update value in third marks only third value as changed + ti1 = ti1iv = ti3 = ti3iv; + ti3changed = true; + await updateTextInputValueToImmediateValue({ + componentName: "/ti3", + core, + }); + + await check_items( + [ti1, ti2, ti3, ti4], + [ti1iv, ti2iv, ti3iv, ti4iv], + [ti1changed, ti2changed, ti3changed, ti4changed], + [ti1ivchanged, ti2ivchanged, ti3ivchanged, ti4ivchanged], + ); + + // type in fourth marks fourth immediate value as changed + ti4iv = "eggplant"; + ti4ivchanged = true; + await updateTextInputImmediateValue({ + text: ti4iv, + componentName: "/ti4", + core, + }); + await check_items( + [ti1, ti2, ti3, ti4], + [ti1iv, ti2iv, ti3iv, ti4iv], + [ti1changed, ti2changed, ti3changed, ti4changed], + [ti1ivchanged, ti2ivchanged, ti3ivchanged, ti4ivchanged], + ); + + // update value in fourth marks only fourth value as changed + ti2 = ti2iv = ti4 = ti4iv; + ti4changed = true; + await updateTextInputValueToImmediateValue({ + componentName: "/ti4", + core, + }); + + await check_items( + [ti1, ti2, ti3, ti4], + [ti1iv, ti2iv, ti3iv, ti4iv], + [ti1changed, ti2changed, ti3changed, ti4changed], + [ti1ivchanged, ti2ivchanged, ti3ivchanged, ti4ivchanged], + ); + + // reload + core = await createTestCore({ + doenetML, + }); + + ti1 = ""; + ti2 = "apple"; + ti3 = ""; + ti4 = "apple"; + ti1iv = ""; + ti2iv = "apple"; + ti3iv = ""; + ti4iv = "apple"; + ti1changed = false; + ti2changed = false; + ti3changed = false; + ti4changed = false; + ti1ivchanged = false; + ti2ivchanged = false; + ti3ivchanged = false; + ti4ivchanged = false; + + await check_items( + [ti1, ti2, ti3, ti4], + [ti1iv, ti2iv, ti3iv, ti4iv], + [ti1changed, ti2changed, ti3changed, ti4changed], + [ti1ivchanged, ti2ivchanged, ti3ivchanged, ti4ivchanged], + ); + + // type in third marks only third immediate value as changed + ti3iv = "banana"; + ti3ivchanged = true; + await updateTextInputImmediateValue({ + text: ti3iv, + componentName: "/ti3", + core, + }); + await check_items( + [ti1, ti2, ti3, ti4], + [ti1iv, ti2iv, ti3iv, ti4iv], + [ti1changed, ti2changed, ti3changed, ti4changed], + [ti1ivchanged, ti2ivchanged, ti3ivchanged, ti4ivchanged], + ); + + // update value in third marks first and third value/immediateValue as changed + ti1 = ti1iv = ti3 = ti3iv; + ti1changed = true; + ti1ivchanged = true; + ti3changed = true; + await updateTextInputValueToImmediateValue({ + componentName: "/ti3", + core, + }); + + await check_items( + [ti1, ti2, ti3, ti4], + [ti1iv, ti2iv, ti3iv, ti4iv], + [ti1changed, ti2changed, ti3changed, ti4changed], + [ti1ivchanged, ti2ivchanged, ti3ivchanged, ti4ivchanged], + ); + + // type in fourth marks only fourth immediate value as changed + ti4iv = "eggplant"; + ti4ivchanged = true; + await updateTextInputImmediateValue({ + text: ti4iv, + componentName: "/ti4", + core, + }); + await check_items( + [ti1, ti2, ti3, ti4], + [ti1iv, ti2iv, ti3iv, ti4iv], + [ti1changed, ti2changed, ti3changed, ti4changed], + [ti1ivchanged, ti2ivchanged, ti3ivchanged, ti4ivchanged], + ); + + // update value in fourth marks second and fourth value/immediateValue as changed + ti2 = ti2iv = ti4 = ti4iv; + ti2changed = true; + ti2ivchanged = true; + ti4changed = true; + await updateTextInputValueToImmediateValue({ + componentName: "/ti4", + core, + }); + + await check_items( + [ti1, ti2, ti3, ti4], + [ti1iv, ti2iv, ti3iv, ti4iv], + [ti1changed, ti2changed, ti3changed, ti4changed], + [ti1ivchanged, ti2ivchanged, ti3ivchanged, ti4ivchanged], + ); + }); + + it("text input with label", async () => { + let core = await createTestCore({ + doenetML: ` +

+

+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/ti1"].stateValues.label).eq("Type something"); + expect(stateVariables["/ti2"].stateValues.label).eq( + "Hello \\(\\frac{a}{b}\\)", + ); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/triggerset.test.ts b/packages/doenetml-worker/src/test/tagSpecific/triggerset.test.ts new file mode 100644 index 000000000..e43851bc6 --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/triggerset.test.ts @@ -0,0 +1,1561 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { cleanLatex } from "../utils/math"; +import { + updateBooleanInputValue, + updateMathInputValue, +} from "../utils/actions"; +import me from "math-expressions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +describe("TriggerSet tag tests", async () => { + async function test_5_triggered_actions(core) { + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/flip"].stateValues.hidden).eq(true); + expect(stateVariables["/addHello"].stateValues.hidden).eq(true); + expect(stateVariables["/addOne"].stateValues.hidden).eq(true); + expect(stateVariables["/rs"].stateValues.hidden).eq(true); + expect(stateVariables["/addPoint"].stateValues.hidden).eq(true); + + expect(stateVariables["/g"].activeChildren.length).eq(1); + + let numbers = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers.length).eq(5); + for (let num of numbers) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(""); + expect(stateVariables["/n"].stateValues.value).eq(1); + + await core.requestAction({ + componentName: "/tset", + actionName: "triggerActions", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/g"].activeChildren.length).eq(2); + + let numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + + expect(numbers2).not.eqls(numbers); + numbers = numbers2; + + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq(" hello"); + expect(stateVariables["/n"].stateValues.value).eq(2); + + await core.requestAction({ + componentName: "/tset", + actionName: "triggerActions", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/g"].activeChildren.length).eq(3); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + + expect(numbers2).not.eqls(numbers); + numbers = numbers2; + + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(" hello hello"); + expect(stateVariables["/n"].stateValues.value).eq(3); + + await core.requestAction({ + componentName: "/tset", + actionName: "triggerActions", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/g"].activeChildren.length).eq(4); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + + expect(numbers2).not.eqls(numbers); + numbers = numbers2; + + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq( + " hello hello hello", + ); + expect(stateVariables["/n"].stateValues.value).eq(4); + } + + it("triggerSet", async () => { + let core = await createTestCore({ + doenetML: ` +

Boolean to swap:

+

Say hello:

+

Count: 1

+ + + (1,2) + + +

+ + + + + + + + + + + + (3,4) + + + `, + }); + + await test_5_triggered_actions(core); + }); + + it("triggerSet and chain to updateValue and call action", async () => { + let core = await createTestCore({ + doenetML: ` +

Boolean to swap:

+

Say hello:

+

Count: 1

+ + + (1,2) + + +

+ + + + + + + + + + + + + + (3,4) + + `, + }); + + await test_5_triggered_actions(core); + }); + + it("triggerSet and chain to triggerSet", async () => { + let core = await createTestCore({ + doenetML: ` +

Boolean to swap:

+

Say hello:

+

Count: 1

+ + + (1,2) + + +

+ + + + + + + + + + + + + + + + (3,4) + + + + `, + }); + + await test_5_triggered_actions(core); + }); + + it("triggerSet and chain multiple sources to triggerSet", async () => { + let core = await createTestCore({ + doenetML: ` +

Boolean to swap:

+

Say hello:

+

Count: 1

+

Count 2: 1

+ + + (1,2) + + +

+ + + + + + + + + + + + + + + + (3,4) + + + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n2"].stateValues.value).eq(1); + + await test_5_triggered_actions(core); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n2"].stateValues.value).eq(1); + let numbers = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(stateVariables["/g"].activeChildren.length).eq(4); + + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq( + " hello hello hello", + ); + expect(stateVariables["/n"].stateValues.value).eq(4); + + await core.requestAction({ + componentName: "/in", + actionName: "updateValue", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n2"].stateValues.value).eq(2); + + expect(stateVariables["/g"].activeChildren.length).eq(5); + + let numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + + expect(numbers2).eqls(numbers); + + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq( + " hello hello hello", + ); + expect(stateVariables["/n"].stateValues.value).eq(5); + }); + + it("triggerSet based on trigger", async () => { + let core = await createTestCore({ + doenetML: ` + + (-1,2) + + x + y + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/trip"].stateValues.hidden).eq(true); + expect(stateVariables["/quad"].stateValues.hidden).eq(true); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("y"); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -1, y: -7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("y"); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 3, y: -4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("y"); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 1, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("4y"); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 5, y: 9 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("4y"); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -3, y: 4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("4y"); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -6, y: 5 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("4y"); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 4, y: 2 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("9x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("16y"); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 9, y: 7 }, + event: null, + }); + }); + + it("triggerSet triggered when click", async () => { + let core = await createTestCore({ + doenetML: ` + + (-1,2) + + x + y + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/trip"].stateValues.hidden).eq(true); + expect(stateVariables["/quad"].stateValues.hidden).eq(true); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("y"); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -1, y: -7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("y"); + + await core.requestAction({ + actionName: "pointClicked", + componentName: "/P", + args: { name: "/P" }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("4y"); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 5, y: 9 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("4y"); + + await core.requestAction({ + actionName: "pointClicked", + componentName: "/P", + args: { name: "/P" }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("9x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("16y"); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 9, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("9x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("16y"); + }); + + it("triggerSet triggered when object focused", async () => { + let core = await createTestCore({ + doenetML: ` + + (-1,2) + + x + y + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/trip"].stateValues.hidden).eq(true); + expect(stateVariables["/quad"].stateValues.hidden).eq(true); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("y"); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -1, y: -7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("y"); + + await core.requestAction({ + actionName: "pointFocused", + componentName: "/P", + args: { name: "/P" }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("4y"); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 5, y: 9 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("4y"); + + await core.requestAction({ + actionName: "pointFocused", + componentName: "/P", + args: { name: "/P" }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("9x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("16y"); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 9, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("9x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("16y"); + }); + + it("triggerWhen supersedes chaining for triggerSet", async () => { + let core = await createTestCore({ + doenetML: ` + + (-1,2) + + +

Boolean to swap:

+

Say hello:

+

Count: 1

+

Count down: 5

+ + + + + + + + + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/ts1"].stateValues.hidden).eq(true); + expect(stateVariables["/ts2"].stateValues.hidden).eq(true); + + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(""); + expect(stateVariables["/n"].stateValues.value).eq(1); + expect(stateVariables["/m"].stateValues.value).eq(5); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -1, y: -7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(""); + expect(stateVariables["/n"].stateValues.value).eq(2); + expect(stateVariables["/m"].stateValues.value).eq(4); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 3, y: -4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(""); + expect(stateVariables["/n"].stateValues.value).eq(2); + expect(stateVariables["/m"].stateValues.value).eq(4); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 1, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq(" hello"); + expect(stateVariables["/n"].stateValues.value).eq(2); + expect(stateVariables["/m"].stateValues.value).eq(4); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 5, y: 9 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq(" hello"); + expect(stateVariables["/n"].stateValues.value).eq(2); + expect(stateVariables["/m"].stateValues.value).eq(4); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -3, y: -4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq(" hello"); + expect(stateVariables["/n"].stateValues.value).eq(3); + expect(stateVariables["/m"].stateValues.value).eq(3); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -6, y: -5 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq(" hello"); + expect(stateVariables["/n"].stateValues.value).eq(3); + expect(stateVariables["/m"].stateValues.value).eq(3); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 4, y: 2 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(" hello hello"); + expect(stateVariables["/n"].stateValues.value).eq(3); + expect(stateVariables["/m"].stateValues.value).eq(3); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 9, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(" hello hello"); + expect(stateVariables["/n"].stateValues.value).eq(3); + expect(stateVariables["/m"].stateValues.value).eq(3); + }); + + it("triggerSet supersedes triggerWhen for updateValue and callAction children", async () => { + let core = await createTestCore({ + doenetML: ` + a + + (-1,2) + + +

Boolean to swap:

+

Say hello:

+

Count: 1

+ +

+ + + + + + + + + + + + (3,4) + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/flip"].stateValues.hidden).eq(true); + expect(stateVariables["/addHello"].stateValues.hidden).eq(true); + expect(stateVariables["/addOne"].stateValues.hidden).eq(true); + expect(stateVariables["/rs"].stateValues.hidden).eq(true); + expect(stateVariables["/addPoint"].stateValues.hidden).eq(true); + + expect(stateVariables["/g"].activeChildren.length).eq(1); + + let numbers = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers.length).eq(5); + for (let num of numbers) { + expect(Number.isInteger(num)).be.true; + expect(num).gte(1); + expect(num).lte(6); + } + + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(""); + expect(stateVariables["/n"].stateValues.value).eq(1); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -1, y: -7 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/g"].activeChildren.length).eq(1); + + let numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers2).eqls(numbers); + + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(""); + expect(stateVariables["/n"].stateValues.value).eq(1); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 3, y: -4 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/g"].activeChildren.length).eq(1); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers2).eqls(numbers); + + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(""); + expect(stateVariables["/n"].stateValues.value).eq(1); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 1, y: 7 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/g"].activeChildren.length).eq(2); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers2).not.eqls(numbers); + numbers = numbers2; + + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq(" hello"); + expect(stateVariables["/n"].stateValues.value).eq(2); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 5, y: 9 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/g"].activeChildren.length).eq(2); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers2).eqls(numbers); + + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq(" hello"); + expect(stateVariables["/n"].stateValues.value).eq(2); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -3, y: -4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/g"].activeChildren.length).eq(2); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers2).eqls(numbers); + + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq(" hello"); + expect(stateVariables["/n"].stateValues.value).eq(2); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -6, y: -5 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/g"].activeChildren.length).eq(2); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers2).eqls(numbers); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 4, y: 2 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/g"].activeChildren.length).eq(3); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers2).not.eqls(numbers); + numbers = numbers2; + + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(" hello hello"); + expect(stateVariables["/n"].stateValues.value).eq(3); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 9, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/g"].activeChildren.length).eq(3); + + numbers2 = stateVariables["/nums"].stateValues.text + .split(",") + .map(Number); + expect(numbers2).eqls(numbers); + + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(" hello hello"); + expect(stateVariables["/n"].stateValues.value).eq(3); + }); + + it("triggerSet supersedes chaining for updateValue children", async () => { + let core = await createTestCore({ + doenetML: ` + + (-1,2) + + +

Boolean to swap:

+

Say hello:

+

Count: 1

+

Count down: 5

+ + + + + + + + + (3,4) + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/ts"].stateValues.hidden).eq(true); + expect(stateVariables["/uv"].stateValues.hidden).eq(true); + + expect(stateVariables["/g"].activeChildren.length).eq(1); + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(""); + expect(stateVariables["/n"].stateValues.value).eq(1); + expect(stateVariables["/m"].stateValues.value).eq(5); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -1, y: -7 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/g"].activeChildren.length).eq(1); + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(""); + expect(stateVariables["/n"].stateValues.value).eq(1); + expect(stateVariables["/m"].stateValues.value).eq(4); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 3, y: -4 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/g"].activeChildren.length).eq(1); + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(""); + expect(stateVariables["/n"].stateValues.value).eq(1); + expect(stateVariables["/m"].stateValues.value).eq(4); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 1, y: 7 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/g"].activeChildren.length).eq(2); + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq(" hello"); + expect(stateVariables["/n"].stateValues.value).eq(2); + expect(stateVariables["/m"].stateValues.value).eq(4); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 5, y: 9 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/g"].activeChildren.length).eq(2); + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq(" hello"); + expect(stateVariables["/n"].stateValues.value).eq(2); + expect(stateVariables["/m"].stateValues.value).eq(4); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -3, y: -4 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/g"].activeChildren.length).eq(2); + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq(" hello"); + expect(stateVariables["/n"].stateValues.value).eq(2); + expect(stateVariables["/m"].stateValues.value).eq(3); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: -6, y: -5 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/g"].activeChildren.length).eq(2); + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq(" hello"); + expect(stateVariables["/n"].stateValues.value).eq(2); + expect(stateVariables["/m"].stateValues.value).eq(3); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 4, y: 2 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/g"].activeChildren.length).eq(3); + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(" hello hello"); + expect(stateVariables["/n"].stateValues.value).eq(3); + expect(stateVariables["/m"].stateValues.value).eq(3); + + await core.requestAction({ + actionName: "movePoint", + componentName: "/P", + args: { x: 9, y: 7 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/g"].activeChildren.length).eq(3); + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(" hello hello"); + expect(stateVariables["/n"].stateValues.value).eq(3); + expect(stateVariables["/m"].stateValues.value).eq(3); + }); + + it("triggerSet with math in label", async () => { + let core = await createTestCore({ + doenetML: ` +

Boolean to swap:

+ + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/tset"].stateValues.label).eq( + "It is \\(\\frac{ \\partial f }{ \\partial x }\\)", + ); + }); + + it("triggerSet with label is name", async () => { + let core = await createTestCore({ + doenetML: ` +

Boolean to swap:

+ + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/trigger-me"].stateValues.label).eq( + "trigger me", + ); + }); + + it("triggerSet in graph", async () => { + let core = await createTestCore({ + doenetML: ` +

n: 1

+ + + + + (3,4) + + + + + + + (-3,-4) + + + + + + +

Anchor 1 coordinates: $triggerSet1.anchor

+

Anchor 2 coordinates: $triggerSet2.anchor

+

Change anchor 1 coordinates:

+

Change anchor 2 coordinates:

+

Position from anchor 1: $triggerSet1.positionFromAnchor

+

Position from anchor 2: $triggerSet2.positionFromAnchor

+

Change position from anchor 1 + + upperRight + upperLeft + lowerRight + lowerLeft + left + right + top + bottom + center + +

+

Change position from anchor 2 + + upperRight + upperLeft + lowerRight + lowerLeft + left + right + top + bottom + center + +

+

Draggable 1: $draggable1

+

Draggable 2: $draggable2

+

Change draggable 1

+

Change draggable 2

+

Disabled 1: $disabled1

+

Disabled 2: $disabled2

+

Change disabled 1

+

Change disabled 2

+

Fixed 1: $fixed1

+

Fixed 2: $fixed2

+

Change fixed 1

+

Change fixed 2

+

FixLocation 1: $fixLocation1

+

FixLocation 2: $fixLocation2

+

Change fixLocation 1

+

Change fixLocation 2

+ + `, + }); + + // TODO: how to click on the buttons and test if they are disabled? + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/pAnchor1"].stateValues.text).eq( + "Anchor 1 coordinates: ( 1, 3 )", + ); + expect(stateVariables["/pAnchor2"].stateValues.text).eq( + "Anchor 2 coordinates: ( 0, 0 )", + ); + expect(stateVariables["/pPositionFromAnchor1"].stateValues.text).eq( + "Position from anchor 1: upperright", + ); + expect(stateVariables["/pPositionFromAnchor2"].stateValues.text).eq( + "Position from anchor 2: center", + ); + expect( + stateVariables["/positionFromAnchor1"].stateValues.selectedIndices, + ).eqls([1]); + expect( + stateVariables["/positionFromAnchor2"].stateValues.selectedIndices, + ).eqls([9]); + expect(stateVariables["/pDraggable1"].stateValues.text).eq( + "Draggable 1: true", + ); + expect(stateVariables["/pDraggable2"].stateValues.text).eq( + "Draggable 2: true", + ); + expect(stateVariables["/pDisabled1"].stateValues.text).eq( + "Disabled 1: true", + ); + expect(stateVariables["/pDisabled2"].stateValues.text).eq( + "Disabled 2: false", + ); + expect(stateVariables["/pFixed1"].stateValues.text).eq( + "Fixed 1: false", + ); + expect(stateVariables["/pFixed2"].stateValues.text).eq( + "Fixed 2: false", + ); + expect(stateVariables["/pFixLocation1"].stateValues.text).eq( + "FixLocation 1: false", + ); + expect(stateVariables["/pFixLocation2"].stateValues.text).eq( + "FixLocation 2: false", + ); + + // move triggerSets by dragging + + await core.requestAction({ + actionName: "moveButton", + componentName: "/triggerSet1", + args: { x: -2, y: 3 }, + event: null, + }); + await core.requestAction({ + actionName: "moveButton", + componentName: "/triggerSet2", + args: { x: 4, y: -5 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/pAnchor1"].stateValues.text).eq( + "Anchor 1 coordinates: ( -2, 3 )", + ); + expect(stateVariables["/pAnchor2"].stateValues.text).eq( + "Anchor 2 coordinates: ( 4, -5 )", + ); + + // move triggerSets by entering coordinates + await updateMathInputValue({ + latex: "(6,7)", + componentName: "/anchorCoords1", + core, + }); + await updateMathInputValue({ + latex: "(8,9)", + componentName: "/anchorCoords2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/pAnchor1"].stateValues.text).eq( + "Anchor 1 coordinates: ( 6, 7 )", + ); + expect(stateVariables["/pAnchor2"].stateValues.text).eq( + "Anchor 2 coordinates: ( 8, 9 )", + ); + + // change position from anchor + await core.requestAction({ + componentName: "/positionFromAnchor1", + actionName: "updateSelectedIndices", + args: { + selectedIndices: [4], + }, + event: null, + }); + await core.requestAction({ + componentName: "/positionFromAnchor2", + actionName: "updateSelectedIndices", + args: { + selectedIndices: [3], + }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pPositionFromAnchor1"].stateValues.text).eq( + "Position from anchor 1: lowerleft", + ); + expect(stateVariables["/pPositionFromAnchor2"].stateValues.text).eq( + "Position from anchor 2: lowerright", + ); + + // make not draggable + await updateBooleanInputValue({ + boolean: false, + componentName: "/draggable1", + core, + }); + await updateBooleanInputValue({ + boolean: false, + componentName: "/draggable2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pDraggable1"].stateValues.text).eq( + "Draggable 1: false", + ); + expect(stateVariables["/pDraggable2"].stateValues.text).eq( + "Draggable 2: false", + ); + + // cannot move triggerSets by dragging + await core.requestAction({ + actionName: "moveButton", + componentName: "/triggerSet1", + args: { x: -10, y: -9 }, + event: null, + }); + await core.requestAction({ + actionName: "moveButton", + componentName: "/triggerSet2", + args: { x: -8, y: -7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pAnchor1"].stateValues.text).eq( + "Anchor 1 coordinates: ( 6, 7 )", + ); + expect(stateVariables["/pAnchor2"].stateValues.text).eq( + "Anchor 2 coordinates: ( 8, 9 )", + ); + + // make draggable again + await updateBooleanInputValue({ + boolean: true, + componentName: "/draggable1", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/draggable2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pDraggable1"].stateValues.text).eq( + "Draggable 1: true", + ); + expect(stateVariables["/pDraggable2"].stateValues.text).eq( + "Draggable 2: true", + ); + + await core.requestAction({ + actionName: "moveButton", + componentName: "/triggerSet1", + args: { x: -10, y: -9 }, + event: null, + }); + await core.requestAction({ + actionName: "moveButton", + componentName: "/triggerSet2", + args: { x: -8, y: -7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pAnchor1"].stateValues.text).eq( + "Anchor 1 coordinates: ( -10, -9 )", + ); + expect(stateVariables["/pAnchor2"].stateValues.text).eq( + "Anchor 2 coordinates: ( -8, -7 )", + ); + + // fix location + await updateBooleanInputValue({ + boolean: true, + componentName: "/fixLocation1", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/fixLocation2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pFixLocation1"].stateValues.text).eq( + "FixLocation 1: true", + ); + expect(stateVariables["/pFixLocation2"].stateValues.text).eq( + "FixLocation 2: true", + ); + + // can change coordinates entering coordinates only for button 1 + + await updateMathInputValue({ + latex: "(1,2)", + componentName: "/anchorCoords1", + core, + }); + await updateMathInputValue({ + latex: "(3,4)", + componentName: "/anchorCoords2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pAnchor1"].stateValues.text).eq( + "Anchor 1 coordinates: ( 1, 2 )", + ); + expect(stateVariables["/pAnchor2"].stateValues.text).eq( + "Anchor 2 coordinates: ( -8, -7 )", + ); + + // cannot move triggerSets by dragging + await core.requestAction({ + actionName: "moveButton", + componentName: "/updateValue1", + args: { x: 4, y: 6 }, + event: null, + }); + await core.requestAction({ + actionName: "moveButton", + componentName: "/updateValue2", + args: { x: 7, y: 8 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pAnchor1"].stateValues.text).eq( + "Anchor 1 coordinates: ( 1, 2 )", + ); + expect(stateVariables["/pAnchor2"].stateValues.text).eq( + "Anchor 2 coordinates: ( -8, -7 )", + ); + + // can change position from anchor only for button 1 + await core.requestAction({ + componentName: "/positionFromAnchor1", + actionName: "updateSelectedIndices", + args: { + selectedIndices: [7], + }, + event: null, + }); + await core.requestAction({ + componentName: "/positionFromAnchor2", + actionName: "updateSelectedIndices", + args: { + selectedIndices: [8], + }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pPositionFromAnchor1"].stateValues.text).eq( + "Position from anchor 1: top", + ); + expect(stateVariables["/pPositionFromAnchor2"].stateValues.text).eq( + "Position from anchor 2: lowerright", + ); + + // can change disabled attribute + await updateBooleanInputValue({ + boolean: false, + componentName: "/disabled1", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/disabled2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pDisabled1"].stateValues.text).eq( + "Disabled 1: false", + ); + expect(stateVariables["/pDisabled2"].stateValues.text).eq( + "Disabled 2: true", + ); + // make completely fixed + await updateBooleanInputValue({ + boolean: true, + componentName: "/fixed1", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/fixed2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pFixed1"].stateValues.text).eq("Fixed 1: true"); + expect(stateVariables["/pFixed2"].stateValues.text).eq("Fixed 2: true"); + + // can change coordinates entering coordinates only for button 1 + await updateMathInputValue({ + latex: "(5,6)", + componentName: "/anchorCoords1", + core, + }); + await updateMathInputValue({ + latex: "(7,8)", + componentName: "/anchorCoords2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pAnchor1"].stateValues.text).eq( + "Anchor 1 coordinates: ( 5, 6 )", + ); + expect(stateVariables["/pAnchor2"].stateValues.text).eq( + "Anchor 2 coordinates: ( -8, -7 )", + ); + + // can change position from anchor only for button 1 + await core.requestAction({ + componentName: "/positionFromAnchor1", + actionName: "updateSelectedIndices", + args: { + selectedIndices: [6], + }, + event: null, + }); + await core.requestAction({ + componentName: "/positionFromAnchor2", + actionName: "updateSelectedIndices", + args: { + selectedIndices: [5], + }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pPositionFromAnchor1"].stateValues.text).eq( + "Position from anchor 1: right", + ); + expect(stateVariables["/pPositionFromAnchor2"].stateValues.text).eq( + "Position from anchor 2: lowerright", + ); + + // can change disabled attribute only for button 1 + await updateBooleanInputValue({ + boolean: true, + componentName: "/disabled1", + core, + }); + await updateBooleanInputValue({ + boolean: false, + componentName: "/disabled2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pDisabled1"].stateValues.text).eq( + "Disabled 1: true", + ); + expect(stateVariables["/pDisabled2"].stateValues.text).eq( + "Disabled 2: true", + ); + }); +}); diff --git a/packages/doenetml-worker/src/test/tagSpecific/updatevalue.test.ts b/packages/doenetml-worker/src/test/tagSpecific/updatevalue.test.ts new file mode 100644 index 000000000..bc01b0094 --- /dev/null +++ b/packages/doenetml-worker/src/test/tagSpecific/updatevalue.test.ts @@ -0,0 +1,2901 @@ +import { describe, expect, it, vi } from "vitest"; +import { createTestCore, returnAllStateVariables } from "../utils/test-core"; +import { cleanLatex } from "../utils/math"; +import { + updateBooleanInputValue, + updateMathInputValue, +} from "../utils/actions"; +import me from "math-expressions"; + +const Mock = vi.fn(); +vi.stubGlobal("postMessage", Mock); + +describe("UpdateValue tag tests", async () => { + it("incrementing graph of line segments", async () => { + let core = await createTestCore({ + doenetML: ` + 20/$count + 2 + + + + + + + + +

+ + + + `, + }); + + let left = -10; + + let stateVariables = await returnAllStateVariables(core); + + let count = 2; + let step = 20 / count; + + expect(stateVariables["/count"].stateValues.value).eq(count); + expect(stateVariables["/step"].stateValues.value).eq(step); + + for (let ind = 1; ind <= count; ind++) { + expect( + me + .fromAst( + stateVariables["/l" + ind + "/ls"].stateValues + .endpoints[0][0], + ) + .evaluate_to_constant(), + ).closeTo(left + (ind - 1) * step, 1e-12); + expect( + me + .fromAst( + stateVariables["/l" + ind + "/ls"].stateValues + .endpoints[0][1], + ) + .evaluate_to_constant(), + ).closeTo(Math.sin(left + (ind - 1) * step), 1e-12); + expect( + me + .fromAst( + stateVariables["/l" + ind + "/ls"].stateValues + .endpoints[1][0], + ) + .evaluate_to_constant(), + ).closeTo(left + ind * step, 1e-12); + expect( + me + .fromAst( + stateVariables["/l" + ind + "/ls"].stateValues + .endpoints[1][1], + ) + .evaluate_to_constant(), + ).closeTo(Math.sin(left + ind * step), 1e-12); + } + + // double number + await core.requestAction({ + componentName: "/uv", + actionName: "updateValue", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + count = 4; + step = 20 / count; + + expect(stateVariables["/count"].stateValues.value).eq(count); + expect(stateVariables["/step"].stateValues.value).eq(step); + + for (let ind = 1; ind <= count; ind++) { + expect( + me + .fromAst( + stateVariables["/l" + ind + "/ls"].stateValues + .endpoints[0][0], + ) + .evaluate_to_constant(), + ).closeTo(left + (ind - 1) * step, 1e-12); + expect( + me + .fromAst( + stateVariables["/l" + ind + "/ls"].stateValues + .endpoints[0][1], + ) + .evaluate_to_constant(), + ).closeTo(Math.sin(left + (ind - 1) * step), 1e-12); + expect( + me + .fromAst( + stateVariables["/l" + ind + "/ls"].stateValues + .endpoints[1][0], + ) + .evaluate_to_constant(), + ).closeTo(left + ind * step, 1e-12); + expect( + me + .fromAst( + stateVariables["/l" + ind + "/ls"].stateValues + .endpoints[1][1], + ) + .evaluate_to_constant(), + ).closeTo(Math.sin(left + ind * step), 1e-12); + } + + // double number a second time + await core.requestAction({ + componentName: "/uv", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + count = 8; + step = 20 / count; + + expect(stateVariables["/count"].stateValues.value).eq(count); + expect(stateVariables["/step"].stateValues.value).eq(step); + + for (let ind = 1; ind <= count; ind++) { + expect( + me + .fromAst( + stateVariables["/l" + ind + "/ls"].stateValues + .endpoints[0][0], + ) + .evaluate_to_constant(), + ).closeTo(left + (ind - 1) * step, 1e-12); + expect( + me + .fromAst( + stateVariables["/l" + ind + "/ls"].stateValues + .endpoints[0][1], + ) + .evaluate_to_constant(), + ).closeTo(Math.sin(left + (ind - 1) * step), 1e-12); + expect( + me + .fromAst( + stateVariables["/l" + ind + "/ls"].stateValues + .endpoints[1][0], + ) + .evaluate_to_constant(), + ).closeTo(left + ind * step, 1e-12); + expect( + me + .fromAst( + stateVariables["/l" + ind + "/ls"].stateValues + .endpoints[1][1], + ) + .evaluate_to_constant(), + ).closeTo(Math.sin(left + ind * step), 1e-12); + } + + // double number a third time + await core.requestAction({ + componentName: "/uv", + actionName: "updateValue", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + count = 16; + step = 20 / count; + + expect(stateVariables["/count"].stateValues.value).eq(count); + expect(stateVariables["/step"].stateValues.value).eq(step); + + for (let ind = 1; ind <= count; ind++) { + expect( + me + .fromAst( + stateVariables["/l" + ind + "/ls"].stateValues + .endpoints[0][0], + ) + .evaluate_to_constant(), + ).closeTo(left + (ind - 1) * step, 1e-12); + expect( + me + .fromAst( + stateVariables["/l" + ind + "/ls"].stateValues + .endpoints[0][1], + ) + .evaluate_to_constant(), + ).closeTo(Math.sin(left + (ind - 1) * step), 1e-12); + expect( + me + .fromAst( + stateVariables["/l" + ind + "/ls"].stateValues + .endpoints[1][0], + ) + .evaluate_to_constant(), + ).closeTo(left + ind * step, 1e-12); + expect( + me + .fromAst( + stateVariables["/l" + ind + "/ls"].stateValues + .endpoints[1][1], + ) + .evaluate_to_constant(), + ).closeTo(Math.sin(left + ind * step), 1e-12); + } + }); + + it("update boolean", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(false); + + await core.requestAction({ + componentName: "/uv", + actionName: "updateValue", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/b"].stateValues.value).eq(true); + + await core.requestAction({ + componentName: "/uv", + actionName: "updateValue", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/b"].stateValues.value).eq(false); + }); + + // catch bug where componentWithSelectableType wasn't + // converting strings to booleans correctly + it("update boolean using string value", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(false); + + await core.requestAction({ + componentName: "/setTrue", + actionName: "updateValue", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(true); + + await core.requestAction({ + componentName: "/setTrue", + actionName: "updateValuesetTrue", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(true); + + await core.requestAction({ + componentName: "/setFalse", + actionName: "updateValue", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(false); + + await core.requestAction({ + componentName: "/setFalse", + actionName: "updateValue", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(false); + + await core.requestAction({ + componentName: "/setTrue", + actionName: "updateValue", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(true); + }); + + it("update number using string value with operator", async () => { + let core = await createTestCore({ + doenetML: ` + 1 + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n"].stateValues.value).eq(1); + + await core.requestAction({ + componentName: "/setToSum", + actionName: "updateValue", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/n"].stateValues.value).eq(2); + }); + + it("update property", async () => { + let core = await createTestCore({ + doenetML: ` + (1,2) + + + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/P"].stateValues.latex)).eq("(1,2)"); + + await core.requestAction({ + componentName: "/uv1", + actionName: "updateValue", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/P"].stateValues.latex)).eq("(2,2)"); + + await core.requestAction({ + componentName: "/uv2", + actionName: "updateValue", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/P"].stateValues.latex)).eq("(4,2)"); + }); + + async function test_update_component_index_points(core) { + let stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/p"].stateValues.latex)).eq("(3,2)"); + expect(cleanLatex(stateVariables["/p2"].stateValues.latex)).eq("(1,5)"); + expect(cleanLatex(stateVariables["/p3"].stateValues.latex)).eq("(7,0)"); + + await core.requestAction({ + componentName: "/uv1", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/p"].stateValues.latex)).eq("(3,2)"); + expect(cleanLatex(stateVariables["/p2"].stateValues.latex)).eq("(6,5)"); + expect(cleanLatex(stateVariables["/p3"].stateValues.latex)).eq("(7,0)"); + + await core.requestAction({ + componentName: "/uv1", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/p"].stateValues.latex)).eq("(3,2)"); + expect(cleanLatex(stateVariables["/p2"].stateValues.latex)).eq("(6,5)"); + expect(cleanLatex(stateVariables["/p3"].stateValues.latex)).eq("(7,0)"); + + await core.requestAction({ + componentName: "/uv2", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/p"].stateValues.latex)).eq("(3,2)"); + expect(cleanLatex(stateVariables["/p2"].stateValues.latex)).eq("(6,5)"); + expect(cleanLatex(stateVariables["/p3"].stateValues.latex)).eq("(6,0)"); + + await core.requestAction({ + componentName: "/uv2", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/p"].stateValues.latex)).eq("(3,2)"); + expect(cleanLatex(stateVariables["/p2"].stateValues.latex)).eq("(6,5)"); + expect(cleanLatex(stateVariables["/p3"].stateValues.latex)).eq("(6,0)"); + } + + it("update componentIndex", async () => { + let core = await createTestCore({ + doenetML: ` + + (3,2) + (1,5) + (7,0) + + + + + + + `, + }); + + await test_update_component_index_points(core); + }); + + it("update componentIndex of group", async () => { + let core = await createTestCore({ + doenetML: ` + + (3,2) + ignore me + (1,5) + ignore me too + (7,0) + + + + + + `, + }); + + await test_update_component_index_points(core); + }); + + it("update componentIndex of group with target subnames", async () => { + let core = await createTestCore({ + doenetML: ` + +

Number 1 and point (3,2).

+

Text hello and line .

+
+ + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq( + "Number 1 and point ( 3, 2 ).", + ); + expect(stateVariables["/p2"].stateValues.text).eq( + "Text hello and line 0 = x - y + 1.", + ); + + await core.requestAction({ + componentName: "/uv1", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq( + "Number 3 and point ( 3, 2 ).", + ); + expect(stateVariables["/p2"].stateValues.text).eq( + "Text hello and line 0 = x - y + 1.", + ); + + await core.requestAction({ + componentName: "/uv2", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq( + "Number 3 and point ( 3, 5 ).", + ); + expect(stateVariables["/p2"].stateValues.text).eq( + "Text hello and line 0 = x - y + 1.", + ); + + await core.requestAction({ + componentName: "/uv3", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq( + "Number 3 and point ( 3, 5 ).", + ); + expect(stateVariables["/p2"].stateValues.text).eq( + "Text bye and line 0 = x - y + 1.", + ); + + await core.requestAction({ + componentName: "/uv4", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/p1"].stateValues.text).eq( + "Number 3 and point ( 3, 5 ).", + ); + expect(stateVariables["/p2"].stateValues.text).eq( + "Text bye and line 0 = x - 2.", + ); + }); + + it("update propIndex", async () => { + let core = await createTestCore({ + doenetML: ` + (3,2,1) + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/p"].stateValues.latex)).eq( + "(3,2,1)", + ); + + await core.requestAction({ + componentName: "/uv1", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/p"].stateValues.latex)).eq( + "(3,6,1)", + ); + + await core.requestAction({ + componentName: "/uv1", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/p"].stateValues.latex)).eq( + "(3,6,1)", + ); + + await core.requestAction({ + componentName: "/uv2", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/p"].stateValues.latex)).eq( + "(3,6,6)", + ); + + await core.requestAction({ + componentName: "/uv2", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/p"].stateValues.latex)).eq( + "(3,6,6)", + ); + }); + + it("update multiple components", async () => { + let core = await createTestCore({ + doenetML: ` + + (3,2) + (1,5) + (7,0) + + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/p"].stateValues.latex)).eq("(3,2)"); + expect(cleanLatex(stateVariables["/p2"].stateValues.latex)).eq("(1,5)"); + expect(cleanLatex(stateVariables["/p3"].stateValues.latex)).eq("(7,0)"); + + await core.requestAction({ + componentName: "/uv1", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/p"].stateValues.latex)).eq("(6,2)"); + expect(cleanLatex(stateVariables["/p2"].stateValues.latex)).eq("(6,5)"); + expect(cleanLatex(stateVariables["/p3"].stateValues.latex)).eq("(6,0)"); + + await core.requestAction({ + componentName: "/uv2", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/p"].stateValues.latex)).eq("(12,2)"); + expect(cleanLatex(stateVariables["/p2"].stateValues.latex)).eq( + "(12,5)", + ); + expect(cleanLatex(stateVariables["/p3"].stateValues.latex)).eq( + "(12,0)", + ); + }); + + it("update property of property", async () => { + let core = await createTestCore({ + doenetML: ` + + (1,2) + (3,4) + + + + + + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/P"].stateValues.latex)).eq("(1,2)"); + + await core.requestAction({ + componentName: "/uv1", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/P"].stateValues.latex)).eq("(2,2)"); + + await core.requestAction({ + componentName: "/uv2", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/P"].stateValues.latex)).eq("(4,2)"); + + await core.requestAction({ + componentName: "/uv3", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/P"].stateValues.latex)).eq("(3,7)"); + + await core.requestAction({ + componentName: "/uv1", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/P"].stateValues.latex)).eq("(6,7)"); + + await core.requestAction({ + componentName: "/uv2", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/P"].stateValues.latex)).eq("(12,7)"); + }); + + it("chained updates", async () => { + let core = await createTestCore({ + doenetML: ` + x + y + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("y"); + expect(stateVariables["/quad"].stateValues.hidden).eq(true); + + await core.requestAction({ + componentName: "/trip", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("4y"); + + await core.requestAction({ + componentName: "/trip", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("9x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("16y"); + }); + + it("chained updates on multiple sources", async () => { + let core = await createTestCore({ + doenetML: ` + x + y + z + + + + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("y"); + expect(cleanLatex(stateVariables["/z"].stateValues.latex)).eq("z"); + expect(stateVariables["/quad"].stateValues.hidden).eq(true); + + await core.requestAction({ + componentName: "/trip", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("4y"); + expect(cleanLatex(stateVariables["/z"].stateValues.latex)).eq("z"); + + await core.requestAction({ + componentName: "/doub", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("16y"); + expect(cleanLatex(stateVariables["/z"].stateValues.latex)).eq("2z"); + + await core.requestAction({ + componentName: "/trip", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("9x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("64y"); + expect(cleanLatex(stateVariables["/z"].stateValues.latex)).eq("2z"); + }); + + it("chained updates, copies don't copy triggers", async () => { + let core = await createTestCore({ + doenetML: ` +

n: 1

+

m1: 1

+

m2: 1

+ +

+

+

+

$uv

+ + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n"].stateValues.value).eq(1); + expect(stateVariables["/m1"].stateValues.value).eq(1); + expect(stateVariables["/m2"].stateValues.value).eq(1); + + await core.requestAction({ + componentName: "/uv", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n"].stateValues.value).eq(2); + expect(stateVariables["/m1"].stateValues.value).eq(2); + expect(stateVariables["/m2"].stateValues.value).eq(1); + + await core.requestAction({ + componentName: "/uv2", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n"].stateValues.value).eq(3); + expect(stateVariables["/m1"].stateValues.value).eq(2); + expect(stateVariables["/m2"].stateValues.value).eq(2); + + await core.requestAction({ + componentName: "/uv3", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n"].stateValues.value).eq(4); + expect(stateVariables["/m1"].stateValues.value).eq(2); + expect(stateVariables["/m2"].stateValues.value).eq(2); + + // Note: we expect the macro to trigger the updateValue with triggerWith="uv" + // because it doesn't have a name. + let macroName = + stateVariables["/pmacro"].activeChildren[0].componentName; + + await core.requestAction({ + componentName: macroName, + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/n"].stateValues.value).eq(5); + expect(stateVariables["/m1"].stateValues.value).eq(3); + expect(stateVariables["/m2"].stateValues.value).eq(2); + }); + + it("update based on trigger", async () => { + let core = await createTestCore({ + doenetML: ` + + (-1,2) + + x + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + expect(stateVariables["/trip"].stateValues.hidden).eq(true); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: -1, y: -7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 3, y: -4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 1, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 5, y: 9 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: -4, y: 4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: -6, y: 5 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 4, y: 2 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("9x"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 9, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("9x"); + }); + + it("update triggered when click", async () => { + let core = await createTestCore({ + doenetML: ` + + (-1,2) + + x + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + expect(stateVariables["/trip"].stateValues.hidden).eq(true); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: -1, y: -7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + + await core.requestAction({ + componentName: "/P", + actionName: "pointClicked", + args: { name: "/P" }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 5, y: 9 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + + await core.requestAction({ + componentName: "/P", + actionName: "pointClicked", + args: { name: "/P" }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("9x"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 9, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("9x"); + }); + + it("update triggered when object focused", async () => { + let core = await createTestCore({ + doenetML: ` + + (-1,2) + + x + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + expect(stateVariables["/trip"].stateValues.hidden).eq(true); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: -1, y: -7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + + await core.requestAction({ + componentName: "/P", + actionName: "pointFocused", + args: { name: "/P" }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 5, y: 9 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + + await core.requestAction({ + componentName: "/P", + actionName: "pointFocused", + args: { name: "/P" }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("9x"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 9, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("9x"); + }); + + it("update triggered when objects clicked, trigger with unnamed copies", async () => { + let core = await createTestCore({ + doenetML: ` + + (-1,2) + + + $P + + + $P{name="P2"} + + + + + + x + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + let PcopyName = + stateVariables["/graph1"].activeChildren[0].componentName; + + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + expect(stateVariables["/trip"].stateValues.hidden).eq(true); + + // clicking unnamed copy triggers update + + await core.requestAction({ + componentName: PcopyName, + actionName: "pointClicked", + args: { name: PcopyName }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + + // clicking copy with an assignNames does not trigger update + await core.requestAction({ + componentName: "/P2", + actionName: "pointClicked", + args: { name: "/P2" }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + + // clicking point with copySource does not trigger update + await core.requestAction({ + componentName: "/_point2", + actionName: "pointClicked", + args: { name: "/_point2" }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + + // clicking unnamed copy triggers update again + await core.requestAction({ + componentName: PcopyName, + actionName: "pointClicked", + args: { name: PcopyName }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("9x"); + }); + + it("chained updates based on trigger", async () => { + let core = await createTestCore({ + doenetML: ` + + (-1,2) + + x + y + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("y"); + expect(stateVariables["/trip"].stateValues.hidden).eq(true); + expect(stateVariables["/quad"].stateValues.hidden).eq(true); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: -1, y: -7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("y"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 3, y: -4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("y"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 1, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("4y"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 5, y: 9 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("4y"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: -3, y: 4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("4y"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: -6, y: 5 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("4y"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 4, y: 2 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("9x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("16y"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 9, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("9x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("16y"); + }); + + it("chained updates based on trigger on same object", async () => { + let core = await createTestCore({ + doenetML: ` + + (-1,2) + + x + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + expect(stateVariables["/trip"].stateValues.hidden).eq(true); + expect(stateVariables["/quad"].stateValues.hidden).eq(true); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: -1, y: -7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 3, y: -4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 1, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("12x"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 5, y: 9 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("12x"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: -3, y: 4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("12x"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: -6, y: 5 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("12x"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 4, y: 2 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("144x"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 9, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("144x"); + }); + + it("triggerWhen supersedes chaining", async () => { + let core = await createTestCore({ + doenetML: ` + + (-1,2) + + x + y + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("y"); + expect(stateVariables["/trip"].stateValues.hidden).eq(true); + expect(stateVariables["/quad"].stateValues.hidden).eq(true); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: -1, y: -7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("4y"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 3, y: -4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("4y"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 1, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("4y"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 5, y: 9 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("4y"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: -3, y: -4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("16y"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: -6, y: -5 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("16y"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 4, y: 2 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("9x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("16y"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 9, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("9x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("16y"); + }); + + async function test_trigger_set(core) { + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(""); + expect(stateVariables["/n"].stateValues.value).eq(1); + + await core.requestAction({ + componentName: "/ts", + actionName: "triggerActions", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq(" hello"); + expect(stateVariables["/n"].stateValues.value).eq(2); + + await core.requestAction({ + componentName: "/ts", + actionName: "triggerActions", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(" hello hello"); + expect(stateVariables["/n"].stateValues.value).eq(3); + + await core.requestAction({ + componentName: "/ts", + actionName: "triggerActions", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq( + " hello hello hello", + ); + expect(stateVariables["/n"].stateValues.value).eq(4); + } + + it("triggerSet", async () => { + let core = await createTestCore({ + doenetML: ` +

Boolean to swap:

+

Say hello:

+

Count: 1

+ + + + + + + + + `, + }); + + await test_trigger_set(core); + }); + + it("triggerSet and chain to updateValue", async () => { + let core = await createTestCore({ + doenetML: ` +

Boolean to swap:

+

Say hello:

+

Count: 1

+ + + + + + + + + + + `, + }); + + await test_trigger_set(core); + }); + + it("triggerSet and chain to triggerSet", async () => { + let core = await createTestCore({ + doenetML: ` +

Boolean to swap:

+

Say hello:

+

Count: 1

+

Count down: 5

+ + + + + + + + + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(""); + expect(stateVariables["/n"].stateValues.value).eq(1); + expect(stateVariables["/m"].stateValues.value).eq(5); + expect(stateVariables["/ts2"].stateValues.hidden).eq(true); + + await core.requestAction({ + componentName: "/ts", + actionName: "triggerActions", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq(" hello"); + expect(stateVariables["/n"].stateValues.value).eq(2); + expect(stateVariables["/m"].stateValues.value).eq(4); + + await core.requestAction({ + componentName: "/ts", + actionName: "triggerActions", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(" hello hello"); + expect(stateVariables["/n"].stateValues.value).eq(3); + expect(stateVariables["/m"].stateValues.value).eq(3); + + await core.requestAction({ + componentName: "/ts", + actionName: "triggerActions", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq( + " hello hello hello", + ); + expect(stateVariables["/n"].stateValues.value).eq(4); + expect(stateVariables["/m"].stateValues.value).eq(2); + }); + + it("triggerSet based on trigger", async () => { + let core = await createTestCore({ + doenetML: ` + + (-1,2) + + x + y + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("y"); + expect(stateVariables["/trip"].stateValues.hidden).eq(true); + expect(stateVariables["/quad"].stateValues.hidden).eq(true); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: -1, y: -7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("y"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 3, y: -4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("y"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 1, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("4y"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 5, y: 9 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("4y"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: -3, y: 4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("4y"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: -6, y: 5 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("3x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("4y"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 4, y: 2 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("9x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("16y"); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 9, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/x"].stateValues.latex)).eq("9x"); + expect(cleanLatex(stateVariables["/y"].stateValues.latex)).eq("16y"); + }); + + it("triggerWhen supersedes chaining for triggerSet", async () => { + let core = await createTestCore({ + doenetML: ` + + (-1,2) + + +

Boolean to swap:

+

Say hello:

+

Count: 1

+

Count down: 5

+ + + + + + + + + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(""); + expect(stateVariables["/n"].stateValues.value).eq(1); + expect(stateVariables["/m"].stateValues.value).eq(5); + expect(stateVariables["/ts1"].stateValues.hidden).eq(true); + expect(stateVariables["/ts2"].stateValues.hidden).eq(true); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: -1, y: -7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(""); + expect(stateVariables["/n"].stateValues.value).eq(2); + expect(stateVariables["/m"].stateValues.value).eq(4); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 3, y: -4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(""); + expect(stateVariables["/n"].stateValues.value).eq(2); + expect(stateVariables["/m"].stateValues.value).eq(4); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 1, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq(" hello"); + expect(stateVariables["/n"].stateValues.value).eq(2); + expect(stateVariables["/m"].stateValues.value).eq(4); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 5, y: 9 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq(" hello"); + expect(stateVariables["/n"].stateValues.value).eq(2); + expect(stateVariables["/m"].stateValues.value).eq(4); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: -3, y: -4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq(" hello"); + expect(stateVariables["/n"].stateValues.value).eq(3); + expect(stateVariables["/m"].stateValues.value).eq(3); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: -6, y: -5 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq(" hello"); + expect(stateVariables["/n"].stateValues.value).eq(3); + expect(stateVariables["/m"].stateValues.value).eq(3); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 4, y: 2 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(" hello hello"); + expect(stateVariables["/n"].stateValues.value).eq(3); + expect(stateVariables["/m"].stateValues.value).eq(3); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 9, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(" hello hello"); + expect(stateVariables["/n"].stateValues.value).eq(3); + expect(stateVariables["/m"].stateValues.value).eq(3); + }); + + it("triggerSet supersedes triggerWhen for updateValue children", async () => { + let core = await createTestCore({ + doenetML: ` + + (-1,2) + + +

Boolean to swap:

+

Say hello:

+

Count: 1

+ + + + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(""); + expect(stateVariables["/n"].stateValues.value).eq(1); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: -1, y: -7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(""); + expect(stateVariables["/n"].stateValues.value).eq(1); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 3, y: -4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(""); + expect(stateVariables["/n"].stateValues.value).eq(1); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 1, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq(" hello"); + expect(stateVariables["/n"].stateValues.value).eq(2); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 5, y: 9 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq(" hello"); + expect(stateVariables["/n"].stateValues.value).eq(2); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: -3, y: -4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq(" hello"); + expect(stateVariables["/n"].stateValues.value).eq(2); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: -6, y: -5 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq(" hello"); + expect(stateVariables["/n"].stateValues.value).eq(2); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 9, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(" hello hello"); + expect(stateVariables["/n"].stateValues.value).eq(3); + }); + + it("triggerSet supersedes chaining for updateValue children", async () => { + let core = await createTestCore({ + doenetML: ` + + (-1,2) + + +

Boolean to swap:

+

Say hello:

+

Count: 1

+

Count down: 5

+ + + + + + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(""); + expect(stateVariables["/n"].stateValues.value).eq(1); + expect(stateVariables["/m"].stateValues.value).eq(5); + expect(stateVariables["/ts"].stateValues.hidden).eq(true); + expect(stateVariables["/uv"].stateValues.hidden).eq(true); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: -1, y: -7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(""); + expect(stateVariables["/n"].stateValues.value).eq(1); + expect(stateVariables["/m"].stateValues.value).eq(4); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 3, y: -4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(""); + expect(stateVariables["/n"].stateValues.value).eq(1); + expect(stateVariables["/m"].stateValues.value).eq(4); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 1, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq(" hello"); + expect(stateVariables["/n"].stateValues.value).eq(2); + expect(stateVariables["/m"].stateValues.value).eq(4); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 5, y: 9 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq(" hello"); + expect(stateVariables["/n"].stateValues.value).eq(2); + expect(stateVariables["/m"].stateValues.value).eq(4); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: -3, y: -4 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq(" hello"); + expect(stateVariables["/n"].stateValues.value).eq(2); + expect(stateVariables["/m"].stateValues.value).eq(3); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: -6, y: -5 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(true); + expect(stateVariables["/hello"].stateValues.value).eq(" hello"); + expect(stateVariables["/n"].stateValues.value).eq(2); + expect(stateVariables["/m"].stateValues.value).eq(3); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 4, y: 2 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(" hello hello"); + expect(stateVariables["/n"].stateValues.value).eq(3); + expect(stateVariables["/m"].stateValues.value).eq(3); + + await core.requestAction({ + componentName: "/P", + actionName: "movePoint", + args: { x: 9, y: 7 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/b"].stateValues.value).eq(false); + expect(stateVariables["/hello"].stateValues.value).eq(" hello hello"); + expect(stateVariables["/n"].stateValues.value).eq(3); + expect(stateVariables["/m"].stateValues.value).eq(3); + }); + + it("update value to blank string", async () => { + let core = await createTestCore({ + doenetML: ` + something + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/t"].stateValues.text).eq("something"); + + await core.requestAction({ + componentName: "/toBlank", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/t"].stateValues.text).eq(""); + }); + + it("updateValue warnings with invalid targets", async () => { + let core = await createTestCore({ + doenetML: ` + 1 +

1

+ + + + + `, + }); + + // click the update value buttons + await core.requestAction({ + componentName: "/uv1", + actionName: "updateValue", + args: {}, + event: null, + }); + await core.requestAction({ + componentName: "/uv2", + actionName: "updateValue", + args: {}, + event: null, + }); + await core.requestAction({ + componentName: "/uv3", + actionName: "updateValue", + args: {}, + event: null, + }); + + let errorWarnings = core.errorWarnings; + + expect(errorWarnings.errors.length).eq(0); + expect(errorWarnings.warnings.length).eq(3); + + expect(errorWarnings.warnings[0].message).contain( + 'Invalid target for : cannot find a state variable named "invalid" on a ', + ); + expect(errorWarnings.warnings[0].level).eq(1); + expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(5); + expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(3); + expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(5); + expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(60); + + expect(errorWarnings.warnings[1].message).contain( + 'Invalid target for : cannot find a state variable named "value" on a

', + ); + expect(errorWarnings.warnings[1].level).eq(1); + expect(errorWarnings.warnings[1].doenetMLrange.lineBegin).eq(6); + expect(errorWarnings.warnings[1].doenetMLrange.charBegin).eq(3); + expect(errorWarnings.warnings[1].doenetMLrange.lineEnd).eq(6); + expect(errorWarnings.warnings[1].doenetMLrange.charEnd).eq(52); + + expect(errorWarnings.warnings[2].message).contain( + "Invalid target for : cannot find target", + ); + expect(errorWarnings.warnings[2].level).eq(1); + expect(errorWarnings.warnings[2].doenetMLrange.lineBegin).eq(7); + expect(errorWarnings.warnings[2].doenetMLrange.charBegin).eq(3); + expect(errorWarnings.warnings[2].doenetMLrange.lineEnd).eq(7); + expect(errorWarnings.warnings[2].doenetMLrange.charEnd).eq(66); + }); + + it("math in label", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/update"].stateValues.label).eq( + "we have \\(\\prod_{i=1}^3 y_i\\)", + ); + }); + + it("label is name", async () => { + let core = await createTestCore({ + doenetML: ` + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/SwapIt"].stateValues.label).eq("Swap It"); + }); + + it("update essential label value", async () => { + let core = await createTestCore({ + doenetML: ` + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/uv"].stateValues.label).eq(""); + + await core.requestAction({ + componentName: "/uv", + actionName: "updateValue", + args: {}, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/uv"].stateValues.label).eq("Hello!"); + }); + + it("bug fix: no duplicate name error, #1921", async () => { + let core = await createTestCore({ + doenetML: ` + + + + + + + + + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/uv1"].stateValues.label).eq("Move tail"); + expect(stateVariables["/ts1"].stateValues.label).eq("Move both"); + expect(cleanLatex(stateVariables["/vh"].stateValues.latex)).eq("(1,0)"); + expect(cleanLatex(stateVariables["/vt"].stateValues.latex)).eq("(0,0)"); + + await core.requestAction({ + componentName: "/uv1", + actionName: "updateValue", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/vh"].stateValues.latex)).eq("(4,4)"); + expect(cleanLatex(stateVariables["/vt"].stateValues.latex)).eq("(3,4)"); + + await core.requestAction({ + componentName: "/ts1", + actionName: "triggerActions", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + expect(cleanLatex(stateVariables["/vh"].stateValues.latex)).eq("(9,4)"); + expect(cleanLatex(stateVariables["/vt"].stateValues.latex)).eq("(7,2)"); + }); + + it("updateValue in graph", async () => { + let core = await createTestCore({ + doenetML: ` +

n: 1

+ + + + + +

Anchor 1 coordinates: $updateValue1.anchor

+

Anchor 2 coordinates: $updateValue2.anchor

+

Change anchor 1 coordinates:

+

Change anchor 2 coordinates:

+

Position from anchor 1: $updateValue1.positionFromAnchor

+

Position from anchor 2: $updateValue2.positionFromAnchor

+

Change position from anchor 1 + + upperRight + upperLeft + lowerRight + lowerLeft + left + right + top + bottom + center + +

+

Change position from anchor 2 + + upperRight + upperLeft + lowerRight + lowerLeft + left + right + top + bottom + center + +

+

Draggable 1: $draggable1

+

Draggable 2: $draggable2

+

Change draggable 1

+

Change draggable 2

+

Disabled 1: $disabled1

+

Disabled 2: $disabled2

+

Change disabled 1

+

Change disabled 2

+

Fixed 1: $fixed1

+

Fixed 2: $fixed2

+

Change fixed 1

+

Change fixed 2

+

FixLocation 1: $fixLocation1

+

FixLocation 2: $fixLocation2

+

Change fixLocation 1

+

Change fixLocation 2

+ + `, + }); + + // TODO: how to click on the buttons and test if they are disabled? + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/pAnchor1"].stateValues.text).eq( + "Anchor 1 coordinates: ( 1, 3 )", + ); + expect(stateVariables["/pAnchor2"].stateValues.text).eq( + "Anchor 2 coordinates: ( 0, 0 )", + ); + expect(stateVariables["/pPositionFromAnchor1"].stateValues.text).eq( + "Position from anchor 1: upperright", + ); + expect(stateVariables["/pPositionFromAnchor2"].stateValues.text).eq( + "Position from anchor 2: center", + ); + expect( + stateVariables["/positionFromAnchor1"].stateValues.selectedIndices, + ).eqls([1]); + expect( + stateVariables["/positionFromAnchor2"].stateValues.selectedIndices, + ).eqls([9]); + expect(stateVariables["/pDraggable1"].stateValues.text).eq( + "Draggable 1: true", + ); + expect(stateVariables["/pDraggable2"].stateValues.text).eq( + "Draggable 2: true", + ); + expect(stateVariables["/pDisabled1"].stateValues.text).eq( + "Disabled 1: true", + ); + expect(stateVariables["/pDisabled2"].stateValues.text).eq( + "Disabled 2: false", + ); + expect(stateVariables["/pFixed1"].stateValues.text).eq( + "Fixed 1: false", + ); + expect(stateVariables["/pFixed2"].stateValues.text).eq( + "Fixed 2: false", + ); + expect(stateVariables["/pFixLocation1"].stateValues.text).eq( + "FixLocation 1: false", + ); + expect(stateVariables["/pFixLocation2"].stateValues.text).eq( + "FixLocation 2: false", + ); + + // move updateValues by dragging + + await core.requestAction({ + actionName: "moveButton", + componentName: "/updateValue1", + args: { x: -2, y: 3 }, + event: null, + }); + await core.requestAction({ + actionName: "moveButton", + componentName: "/updateValue2", + args: { x: 4, y: -5 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/pAnchor1"].stateValues.text).eq( + "Anchor 1 coordinates: ( -2, 3 )", + ); + expect(stateVariables["/pAnchor2"].stateValues.text).eq( + "Anchor 2 coordinates: ( 4, -5 )", + ); + + // move updateValues by entering coordinates + + await updateMathInputValue({ + latex: "(6,7)", + componentName: "/anchorCoords1", + core, + }); + await updateMathInputValue({ + latex: "(8,9)", + componentName: "/anchorCoords2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/pAnchor1"].stateValues.text).eq( + "Anchor 1 coordinates: ( 6, 7 )", + ); + expect(stateVariables["/pAnchor2"].stateValues.text).eq( + "Anchor 2 coordinates: ( 8, 9 )", + ); + + // change position from anchor + await core.requestAction({ + componentName: "/positionFromAnchor1", + actionName: "updateSelectedIndices", + args: { + selectedIndices: [4], + }, + event: null, + }); + await core.requestAction({ + componentName: "/positionFromAnchor2", + actionName: "updateSelectedIndices", + args: { + selectedIndices: [3], + }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pPositionFromAnchor1"].stateValues.text).eq( + "Position from anchor 1: lowerleft", + ); + expect(stateVariables["/pPositionFromAnchor2"].stateValues.text).eq( + "Position from anchor 2: lowerright", + ); + + // make not draggable + await updateBooleanInputValue({ + boolean: false, + componentName: "/draggable1", + core, + }); + await updateBooleanInputValue({ + boolean: false, + componentName: "/draggable2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pDraggable1"].stateValues.text).eq( + "Draggable 1: false", + ); + expect(stateVariables["/pDraggable2"].stateValues.text).eq( + "Draggable 2: false", + ); + + // cannot move updateValues by dragging + await core.requestAction({ + actionName: "moveButton", + componentName: "/updateValue1", + args: { x: -10, y: -9 }, + event: null, + }); + await core.requestAction({ + actionName: "moveButton", + componentName: "/updateValue2", + args: { x: -8, y: -7 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pAnchor1"].stateValues.text).eq( + "Anchor 1 coordinates: ( 6, 7 )", + ); + expect(stateVariables["/pAnchor2"].stateValues.text).eq( + "Anchor 2 coordinates: ( 8, 9 )", + ); + + // make draggable again + await updateBooleanInputValue({ + boolean: true, + componentName: "/draggable1", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/draggable2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pDraggable1"].stateValues.text).eq( + "Draggable 1: true", + ); + expect(stateVariables["/pDraggable2"].stateValues.text).eq( + "Draggable 2: true", + ); + + await core.requestAction({ + actionName: "moveButton", + componentName: "/updateValue1", + args: { x: -10, y: -9 }, + event: null, + }); + await core.requestAction({ + actionName: "moveButton", + componentName: "/updateValue2", + args: { x: -8, y: -7 }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pAnchor1"].stateValues.text).eq( + "Anchor 1 coordinates: ( -10, -9 )", + ); + expect(stateVariables["/pAnchor2"].stateValues.text).eq( + "Anchor 2 coordinates: ( -8, -7 )", + ); + + // fix location + await updateBooleanInputValue({ + boolean: true, + componentName: "/fixLocation1", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/fixLocation2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pFixLocation1"].stateValues.text).eq( + "FixLocation 1: true", + ); + expect(stateVariables["/pFixLocation2"].stateValues.text).eq( + "FixLocation 2: true", + ); + + // can change coordinates entering coordinates only for button 1 + await updateMathInputValue({ + latex: "(1,2)", + componentName: "/anchorCoords1", + core, + }); + await updateMathInputValue({ + latex: "(3,4)", + componentName: "/anchorCoords2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pAnchor1"].stateValues.text).eq( + "Anchor 1 coordinates: ( 1, 2 )", + ); + expect(stateVariables["/pAnchor2"].stateValues.text).eq( + "Anchor 2 coordinates: ( -8, -7 )", + ); + + // cannot move updateValues by dragging + await core.requestAction({ + actionName: "moveButton", + componentName: "/updateValue1", + args: { x: 4, y: 6 }, + event: null, + }); + await core.requestAction({ + actionName: "moveButton", + componentName: "/updateValue2", + args: { x: 7, y: 8 }, + event: null, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pAnchor1"].stateValues.text).eq( + "Anchor 1 coordinates: ( 1, 2 )", + ); + expect(stateVariables["/pAnchor2"].stateValues.text).eq( + "Anchor 2 coordinates: ( -8, -7 )", + ); + + // can change position from anchor only for button 1 + await core.requestAction({ + componentName: "/positionFromAnchor1", + actionName: "updateSelectedIndices", + args: { + selectedIndices: [7], + }, + event: null, + }); + await core.requestAction({ + componentName: "/positionFromAnchor2", + actionName: "updateSelectedIndices", + args: { + selectedIndices: [8], + }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pPositionFromAnchor1"].stateValues.text).eq( + "Position from anchor 1: top", + ); + expect(stateVariables["/pPositionFromAnchor2"].stateValues.text).eq( + "Position from anchor 2: lowerright", + ); + + // can change disabled attribute + + await updateBooleanInputValue({ + boolean: false, + componentName: "/disabled1", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/disabled2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pDisabled1"].stateValues.text).eq( + "Disabled 1: false", + ); + expect(stateVariables["/pDisabled2"].stateValues.text).eq( + "Disabled 2: true", + ); + + // make completely fixed + + await updateBooleanInputValue({ + boolean: true, + componentName: "/fixed1", + core, + }); + await updateBooleanInputValue({ + boolean: true, + componentName: "/fixed2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pFixed1"].stateValues.text).eq("Fixed 1: true"); + expect(stateVariables["/pFixed2"].stateValues.text).eq("Fixed 2: true"); + + // can change coordinates entering coordinates only for button 1 + await updateMathInputValue({ + latex: "(5,6)", + componentName: "/anchorCoords1", + core, + }); + await updateMathInputValue({ + latex: "(7,8)", + componentName: "/anchorCoords2", + core, + }); + + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pAnchor1"].stateValues.text).eq( + "Anchor 1 coordinates: ( 5, 6 )", + ); + expect(stateVariables["/pAnchor2"].stateValues.text).eq( + "Anchor 2 coordinates: ( -8, -7 )", + ); + + // can change position from anchor only for button 1 + await core.requestAction({ + componentName: "/positionFromAnchor1", + actionName: "updateSelectedIndices", + args: { + selectedIndices: [6], + }, + event: null, + }); + await core.requestAction({ + componentName: "/positionFromAnchor2", + actionName: "updateSelectedIndices", + args: { + selectedIndices: [5], + }, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pPositionFromAnchor1"].stateValues.text).eq( + "Position from anchor 1: right", + ); + expect(stateVariables["/pPositionFromAnchor2"].stateValues.text).eq( + "Position from anchor 2: lowerright", + ); + + // can change disabled attribute only for button 1 + + await updateBooleanInputValue({ + boolean: true, + componentName: "/disabled1", + core, + }); + await updateBooleanInputValue({ + boolean: false, + componentName: "/disabled2", + core, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/pDisabled1"].stateValues.text).eq( + "Disabled 1: true", + ); + expect(stateVariables["/pDisabled2"].stateValues.text).eq( + "Disabled 2: true", + ); + }); + + it("handle removed updateValue when shadowing", async () => { + let core = await createTestCore({ + doenetML: ` +
+ + + + +

true

+ + + + + + + +
+
+
+ + `, + }); + + let stateVariables = await returnAllStateVariables(core); + expect(stateVariables["/grp2/p"].stateValues.text).eq("true"); + expect( + stateVariables["/sec"].activeChildren.filter((x) => x.componentName) + .length, + ).eq(3); + + await core.requestAction({ + componentName: "/grp2/uv", + actionName: "updateValue", + args: {}, + event: null, + }); + stateVariables = await returnAllStateVariables(core); + + expect(stateVariables["/grp2/p"].stateValues.text).eq("false"); + expect( + stateVariables["/sec"].activeChildren.filter((x) => x.componentName) + .length, + ).eq(2); + }); +}); diff --git a/packages/doenetml-worker/src/test/utils/actions.ts b/packages/doenetml-worker/src/test/utils/actions.ts index 71930a5ed..1cf856267 100644 --- a/packages/doenetml-worker/src/test/utils/actions.ts +++ b/packages/doenetml-worker/src/test/utils/actions.ts @@ -23,6 +23,38 @@ export async function updateTextInputValue({ }); } +export async function updateTextInputImmediateValue({ + text, + componentName, + core, +}: { + text: string; + componentName: string; + core: Core; +}) { + await core.requestAction({ + componentName, + actionName: "updateImmediateValue", + args: { text }, + event: null, + }); +} + +export async function updateTextInputValueToImmediateValue({ + componentName, + core, +}: { + componentName: string; + core: Core; +}) { + await core.requestAction({ + componentName, + actionName: "updateValue", + args: {}, + event: null, + }); +} + export async function updateMathInputValue({ latex, componentName, diff --git a/packages/doenetml-worker/src/test/utils/test-core.ts b/packages/doenetml-worker/src/test/utils/test-core.ts index 80551957d..eb5910055 100644 --- a/packages/doenetml-worker/src/test/utils/test-core.ts +++ b/packages/doenetml-worker/src/test/utils/test-core.ts @@ -54,7 +54,7 @@ export async function returnAllStateVariables(core) { stateValues: any; activeChildren: any[]; replacements: null | any[]; - replacementsToWithhold: null | any[]; + replacementsToWithhold: null | number; replacementOf: any; sharedParameters: any; }; diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/booleaninput.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/booleaninput.cy.js index 5520f9676..64579a8a3 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/booleaninput.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/booleaninput.cy.js @@ -6,494 +6,6 @@ describe("BooleanInput Tag Tests", function () { cy.visit("/"); }); - it("single boolean input", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - $bi1.value{assignNames="v1"} - $v1{name="v2"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test values displayed in browser"); - - cy.get(cesc("#\\/v1")).should("have.text", "false"); - cy.get(cesc("#\\/v2")).should("have.text", "false"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/bi1"].stateValues.value).eq(false); - expect(stateVariables["/v1"].stateValues.value).eq(false); - expect(stateVariables["/v2"].stateValues.value).eq(false); - expect(stateVariables["/bi1"].stateValues.label).eq("hello"); - }); - - cy.log("check the box"); - cy.get(cesc("#\\/bi1")).click(); - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/v1")).should("have.text", "true"); - cy.get(cesc("#\\/v2")).should("have.text", "true"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/bi1"].stateValues.value).eq(true); - expect(stateVariables["/v1"].stateValues.value).eq(true); - expect(stateVariables["/v2"].stateValues.value).eq(true); - }); - - cy.log("uncheck the box"); - cy.get(cesc("#\\/bi1")).click(); - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/v1")).should("have.text", "false"); - cy.get(cesc("#\\/v2")).should("have.text", "false"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/bi1"].stateValues.value).eq(false); - expect(stateVariables["/v1"].stateValues.value).eq(false); - expect(stateVariables["/v2"].stateValues.value).eq(false); - }); - }); - - it("single boolean input, starts checked", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - $_booleaninput1.value{assignNames="v1"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/v1")).should("have.text", "true"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - true, - ); - expect(stateVariables["/v1"].stateValues.value).eq(true); - }); - - cy.log("uncheck the box"); - cy.get(cesc("#\\/_booleaninput1")).click(); - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/v1")).should("have.text", "false"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - false, - ); - expect(stateVariables["/v1"].stateValues.value).eq(false); - }); - - cy.log("recheck the box"); - cy.get(cesc("#\\/_booleaninput1")).click(); - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/v1")).should("have.text", "true"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - true, - ); - expect(stateVariables["/v1"].stateValues.value).eq(true); - }); - }); - - it("copied boolean input", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- -

-

-

$bi1.value{assignNames="v1"}

-

- -

-

$bi2.value{assignNames="v2"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/v1")).should("have.text", "true"); - cy.get(cesc("#\\/v2")).should("have.text", "false"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/bi1"].stateValues.value).eq(true); - expect(stateVariables["/bi1a"].stateValues.value).eq(true); - expect(stateVariables["/bi2"].stateValues.value).eq(false); - expect(stateVariables["/v1"].stateValues.value).eq(true); - expect(stateVariables["/v2"].stateValues.value).eq(false); - expect(stateVariables["/bi1"].stateValues.label).eq("green"); - expect(stateVariables["/bi2"].stateValues.label).eq("red"); - }); - - cy.log("click the first input"); - cy.get(cesc("#\\/bi1")).click(); - cy.get(cesc("#\\/v1")).should("have.text", "false"); - cy.get(cesc("#\\/v2")).should("have.text", "false"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/bi1"].stateValues.value).eq(false); - expect(stateVariables["/bi1a"].stateValues.value).eq(false); - expect(stateVariables["/bi2"].stateValues.value).eq(false); - expect(stateVariables["/v1"].stateValues.value).eq(false); - expect(stateVariables["/v2"].stateValues.value).eq(false); - }); - - cy.log("click the second input"); - cy.get(cesc("#\\/bi1a")).click(); - cy.get(cesc("#\\/v1")).should("have.text", "true"); - cy.get(cesc("#\\/v2")).should("have.text", "false"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/bi1"].stateValues.value).eq(true); - expect(stateVariables["/bi1a"].stateValues.value).eq(true); - expect(stateVariables["/bi2"].stateValues.value).eq(false); - expect(stateVariables["/v1"].stateValues.value).eq(true); - expect(stateVariables["/v2"].stateValues.value).eq(false); - }); - - cy.log("click the third input"); - cy.get(cesc("#\\/bi2")).click(); - cy.get(cesc("#\\/v1")).should("have.text", "true"); - cy.get(cesc("#\\/v2")).should("have.text", "true"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/bi1"].stateValues.value).eq(true); - expect(stateVariables["/bi1a"].stateValues.value).eq(true); - expect(stateVariables["/bi2"].stateValues.value).eq(true); - expect(stateVariables["/v1"].stateValues.value).eq(true); - expect(stateVariables["/v2"].stateValues.value).eq(true); - }); - }); - - it("downstream from booleaninput", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Original boolean: true

-

booleaninput based on boolean:

-

Copied boolean: $_boolean1{name="b2"}

-

Copied boolean input: $_booleaninput1.value{assignNames="b3"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/_boolean1")).should("have.text", "true"); - cy.get(cesc("#\\/b2")).should("have.text", "true"); - cy.get(cesc("#\\/b3")).should("have.text", "true"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - true, - ); - expect(stateVariables["/_boolean1"].stateValues.value).eq(true); - expect(stateVariables["/b2"].stateValues.value).eq(true); - expect(stateVariables["/b3"].stateValues.value).eq(true); - }); - - cy.log("change value"); - cy.get(cesc("#\\/_booleaninput1")).click(); - - // cy.get(cesc('#\\/_booleaninput1_input')).should('not.have.attr', 'checked'); - - cy.get(cesc("#\\/_boolean1")).should("have.text", "false"); - cy.get(cesc("#\\/b2")).should("have.text", "false"); - cy.get(cesc("#\\/b3")).should("have.text", "false"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - false, - ); - expect(stateVariables["/_boolean1"].stateValues.value).eq(false); - expect(stateVariables["/b2"].stateValues.value).eq(false); - expect(stateVariables["/b3"].stateValues.value).eq(false); - }); - - cy.log("prefill ignored"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - b -

Original boolean: true

-

booleaninput based on boolean:

-

Value:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "b"); // to wait until loaded - - cy.get(cesc("#\\/_boolean1")).should("have.text", "true"); - cy.get(cesc("#\\/bi2")).should("have.text", "true"); - - cy.log("change value"); - cy.get(cesc("#\\/_booleaninput1")).click(); - - cy.get(cesc("#\\/_boolean1")).should("have.text", "false"); - cy.get(cesc("#\\/bi2")).should("have.text", "false"); - - cy.log("values revert if not updatable"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - c -

Original boolean: can't update me

-

booleaninput based on boolean:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "c"); // to wait until loaded - - // cy.get(cesc('#\\/_booleaninput1_input')).should('not.have.attr', 'checked'); - - cy.get(cesc("#\\/_boolean1")).should("have.text", `false`); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - false, - ); - expect(stateVariables["/_boolean1"].stateValues.value).eq(false); - }); - - cy.log("change value, but it reverts"); - cy.get(cesc("#\\/_booleaninput1")).click(); - - // cy.get(cesc('#\\/_booleaninput1_input')).should('not.have.attr', 'checked'); - - cy.get(cesc("#\\/_boolean1")).should("have.text", `false`); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - false, - ); - expect(stateVariables["/_boolean1"].stateValues.value).eq(false); - }); - }); - - it("downstream from booleaninput via child", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Original boolean: true

-

booleaninput based on boolean: $_boolean1

-

Copied boolean: $_boolean1{name="b2"}

-

Copied boolean input: $_booleaninput1.value{assignNames="b3"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/_boolean1")).should("have.text", "true"); - cy.get(cesc("#\\/b2")).should("have.text", "true"); - cy.get(cesc("#\\/b3")).should("have.text", "true"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - true, - ); - expect(stateVariables["/_boolean1"].stateValues.value).eq(true); - expect(stateVariables["/b2"].stateValues.value).eq(true); - expect(stateVariables["/b3"].stateValues.value).eq(true); - }); - - cy.log("change value"); - cy.get(cesc("#\\/_booleaninput1")).click(); - - cy.get(cesc("#\\/_boolean1")).should("have.text", "false"); - cy.get(cesc("#\\/b2")).should("have.text", "false"); - cy.get(cesc("#\\/b3")).should("have.text", "false"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - false, - ); - expect(stateVariables["/_boolean1"].stateValues.value).eq(false); - expect(stateVariables["/b2"].stateValues.value).eq(false); - expect(stateVariables["/b3"].stateValues.value).eq(false); - }); - - cy.log("prefill ignored"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - b -

Original boolean: true

-

booleaninput based on boolean: $_boolean1

-

Value:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "b"); // to wait until loaded - - cy.get(cesc("#\\/_boolean1")).should("have.text", "true"); - cy.get(cesc("#\\/bi2")).should("have.text", "true"); - - cy.log("change value"); - cy.get(cesc("#\\/_booleaninput1")).click(); - - cy.get(cesc("#\\/_boolean1")).should("have.text", "false"); - cy.get(cesc("#\\/bi2")).should("have.text", "false"); - - cy.log("bindValueTo ignored"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - bb -

Original boolean: true

-

Not bound: false

-

booleaninput based on boolean: $_boolean1

-

Value:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "bb"); // to wait until loaded - - cy.get(cesc("#\\/_boolean1")).should("have.text", "true"); - cy.get(cesc("#\\/_boolean2")).should("have.text", "false"); - cy.get(cesc("#\\/bi2")).should("have.text", "true"); - - cy.log("change value"); - cy.get(cesc("#\\/_booleaninput1")).click(); - - cy.get(cesc("#\\/_boolean1")).should("have.text", "false"); - cy.get(cesc("#\\/_boolean2")).should("have.text", "false"); - cy.get(cesc("#\\/bi2")).should("have.text", "false"); - - cy.log("values revert if not updatable"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - c -

booleaninput based on boolean: can't update

-

Value:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "c"); // to wait until loaded - - cy.get(cesc("#\\/bi2")).should("have.text", `false`); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - false, - ); - expect(stateVariables["/bi2"].stateValues.value).eq(false); - }); - - cy.log("change value, but it reverts"); - cy.get(cesc("#\\/_booleaninput1")).click(); - - cy.get(cesc("#\\/bi2")).should("have.text", `false`); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_booleaninput1"].stateValues.value).eq( - false, - ); - expect(stateVariables["/bi2"].stateValues.value).eq(false); - }); - }); - - it("chain update off booleaninput", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - 1 - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/n")).should("have.text", "1"); - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/n")).should("have.text", "2"); - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/n")).should("have.text", "3"); - }); - it("boolean input as toggle button", () => { cy.window().then(async (win) => { win.postMessage( @@ -797,546 +309,4 @@ describe("BooleanInput Tag Tests", function () { ); }); }); - - it("boolean input in graph", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - -

Anchor 1 coordinates: $booleaninput1.anchor

-

Anchor 2 coordinates: $booleaninput2.anchor

-

Change anchor 1 coordinates:

-

Change anchor 2 coordinates:

-

Position from anchor 1: $booleaninput1.positionFromAnchor

-

Position from anchor 2: $booleaninput2.positionFromAnchor

-

Change position from anchor 1 - - upperRight - upperLeft - lowerRight - lowerLeft - left - right - top - bottom - center - -

-

Change position from anchor 2 - - upperRight - upperLeft - lowerRight - lowerLeft - left - right - top - bottom - center - -

-

Draggable 1: $draggable1

-

Draggable 2: $draggable2

-

Change draggable 1

-

Change draggable 2

-

Disabled 1: $disabled1

-

Disabled 2: $disabled2

-

Change disabled 1

-

Change disabled 2

-

Fixed 1: $fixed1

-

Fixed 2: $fixed2

-

Change fixed 1

-

Change fixed 2

-

FixLocation 1: $fixLocation1

-

FixLocation 2: $fixLocation2

-

Change fixLocation 1

-

Change fixLocation 2

-

- - `, - }, - "*", - ); - }); - - // TODO: how to click on the checkboxes and test if they are disabled? - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,3)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,0)"); - - cy.get(cesc("#\\/pPositionFromAnchor1")).should( - "have.text", - "Position from anchor 1: upperright", - ); - cy.get(cesc("#\\/pPositionFromAnchor2")).should( - "have.text", - "Position from anchor 2: center", - ); - cy.get(cesc("#\\/positionFromAnchor1")).should("have.value", "1"); - cy.get(cesc("#\\/positionFromAnchor2")).should("have.value", "9"); - cy.get(cesc("#\\/pDraggable1")).should( - "have.text", - "Draggable 1: true", - ); - cy.get(cesc("#\\/pDraggable2")).should( - "have.text", - "Draggable 2: true", - ); - - cy.log("move booleaninputs by dragging"); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveInput", - componentName: "/booleaninput1", - args: { x: -2, y: 3 }, - }); - win.callAction1({ - actionName: "moveInput", - componentName: "/booleaninput2", - args: { x: 4, y: -5 }, - }); - }); - - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow").should( - "contain.text", - "(4,−5)", - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−2,3)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(4,−5)"); - - cy.log("move booleaninputs by entering coordinates"); - - cy.get(cesc("#\\/anchorCoords1") + " textarea").type( - "{home}{shift+end}{backspace}(6,7){enter}", - { force: true }, - ); - cy.get(cesc("#\\/anchorCoords2") + " textarea").type( - "{home}{shift+end}{backspace}(8,9){enter}", - { force: true }, - ); - - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow").should( - "contain.text", - "(8,9)", - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(6,7)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(8,9)"); - - cy.log("change position from anchor"); - cy.get(cesc("#\\/positionFromAnchor1")).select("lowerLeft"); - cy.get(cesc("#\\/positionFromAnchor2")).select("lowerRight"); - - cy.get(cesc("#\\/pPositionFromAnchor1")).should( - "have.text", - "Position from anchor 1: lowerleft", - ); - cy.get(cesc("#\\/pPositionFromAnchor2")).should( - "have.text", - "Position from anchor 2: lowerright", - ); - - cy.log("make not draggable"); - - cy.get(cesc("#\\/draggable1")).click(); - cy.get(cesc("#\\/draggable2")).click(); - cy.get(cesc("#\\/pDraggable1")).should( - "have.text", - "Draggable 1: false", - ); - cy.get(cesc("#\\/pDraggable2")).should( - "have.text", - "Draggable 2: false", - ); - - cy.log("cannot move booleaninputs by dragging"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveInput", - componentName: "/booleaninput1", - args: { x: -10, y: -9 }, - }); - win.callAction1({ - actionName: "moveInput", - componentName: "/booleaninput2", - args: { x: -8, y: -7 }, - }); - }); - - // since nothing will change, wait for boolean input to change to know core has responded - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/b")).should("have.text", "true"); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(6,7)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(8,9)"); - - cy.log("make draggable again"); - - cy.get(cesc("#\\/draggable1")).click(); - cy.get(cesc("#\\/draggable2")).click(); - cy.get(cesc("#\\/pDraggable1")).should( - "have.text", - "Draggable 1: true", - ); - cy.get(cesc("#\\/pDraggable2")).should( - "have.text", - "Draggable 2: true", - ); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveInput", - componentName: "/booleaninput1", - args: { x: -10, y: -9 }, - }); - win.callAction1({ - actionName: "moveInput", - componentName: "/booleaninput2", - args: { x: -8, y: -7 }, - }); - }); - - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow").should( - "contain.text", - "(−8,−7)", - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−10,−9)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−8,−7)"); - - cy.log("fix location"); - - cy.get(cesc("#\\/fixLocation1")).click(); - cy.get(cesc("#\\/fixLocation2")).click(); - cy.get(cesc("#\\/pFixLocation1")).should( - "have.text", - "FixLocation 1: true", - ); - cy.get(cesc("#\\/pFixLocation2")).should( - "have.text", - "FixLocation 2: true", - ); - - cy.log("can change coordinates entering coordinates only for input 1"); - - cy.get(cesc("#\\/anchorCoords2") + " textarea").type( - "{home}{shift+end}{backspace}(3,4){enter}", - { force: true }, - ); - cy.get(cesc("#\\/anchorCoords1") + " textarea").type( - "{home}{shift+end}{backspace}(1,2){enter}", - { force: true }, - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow").should( - "contain.text", - "(1,2)", - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−8,−7)"); - - cy.log("cannot move booleaninputs by dragging"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveInput", - componentName: "/booleaninput1", - args: { x: 4, y: 6 }, - }); - win.callAction1({ - actionName: "moveInput", - componentName: "/booleaninput2", - args: { x: 7, y: 8 }, - }); - }); - - // since nothing will change, wait for boolean input to change to know core has responded - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/b")).should("have.text", "false"); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−8,−7)"); - - cy.log("can change position from anchor only for input 1"); - cy.get(cesc("#\\/positionFromAnchor2")).select("bottom"); - cy.get(cesc("#\\/positionFromAnchor1")).select("top"); - - cy.get(cesc("#\\/pPositionFromAnchor1")).should( - "have.text", - "Position from anchor 1: top", - ); - cy.get(cesc("#\\/pPositionFromAnchor2")).should( - "have.text", - "Position from anchor 2: lowerright", - ); - - cy.log("can change disabled attribute"); - cy.get(cesc("#\\/disabled1")).click(); - cy.get(cesc("#\\/disabled2")).click(); - cy.get(cesc("#\\/pDisabled1")).should("have.text", "Disabled 1: false"); - cy.get(cesc("#\\/pDisabled2")).should("have.text", "Disabled 2: true"); - - cy.log("make completely fixed"); - cy.get(cesc("#\\/fixed1")).click(); - cy.get(cesc("#\\/fixed2")).click(); - cy.get(cesc("#\\/pFixed1")).should("have.text", "Fixed 1: true"); - cy.get(cesc("#\\/pFixed2")).should("have.text", "Fixed 2: true"); - - cy.log("can change coordinates entering coordinates only for input 1"); - - cy.get(cesc("#\\/anchorCoords2") + " textarea").type( - "{home}{shift+end}{backspace}(7,8){enter}", - { force: true }, - ); - cy.get(cesc("#\\/anchorCoords1") + " textarea").type( - "{home}{shift+end}{backspace}(5,6){enter}", - { force: true }, - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow").should( - "contain.text", - "(5,6)", - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(5,6)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−8,−7)"); - - cy.log("can change position from anchor only for input 1"); - cy.get(cesc("#\\/positionFromAnchor2")).select("left"); - cy.get(cesc("#\\/positionFromAnchor1")).select("right"); - - cy.get(cesc("#\\/pPositionFromAnchor1")).should( - "have.text", - "Position from anchor 1: right", - ); - cy.get(cesc("#\\/pPositionFromAnchor2")).should( - "have.text", - "Position from anchor 2: lowerright", - ); - - cy.log("can change disabled attribute only for input 1"); - cy.get(cesc("#\\/disabled2")).click(); - cy.get(cesc("#\\/disabled1")).click(); - cy.get(cesc("#\\/pDisabled1")).should("have.text", "Disabled 1: true"); - cy.get(cesc("#\\/pDisabled2")).should("have.text", "Disabled 2: true"); - }); - - it("valueChanged", () => { - let doenetML = ` -

-

-

-

$bi2

- - `; - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - }, - "*", - ); - }); - - cy.get(cesc2("#/bi1_input")).should("not.be.checked"); - cy.get(cesc2("#/bi2_input")).should("be.checked"); - cy.get(cesc2("#/bi3_input")).should("not.be.checked"); - cy.get(cesc2("#/bi4_input")).should("be.checked"); - - cy.get(cesc2("#/bi1a")).should("have.text", "false"); - cy.get(cesc2("#/bi2a")).should("have.text", "true"); - cy.get(cesc2("#/bi3a")).should("have.text", "false"); - cy.get(cesc2("#/bi4a")).should("have.text", "true"); - - cy.get(cesc2("#/bi1changed")).should("have.text", "false"); - cy.get(cesc2("#/bi2changed")).should("have.text", "false"); - cy.get(cesc2("#/bi3changed")).should("have.text", "false"); - cy.get(cesc2("#/bi4changed")).should("have.text", "false"); - - cy.log("clicking first marks only first as changed"); - - cy.get(cesc2("#/bi1")).click(); - - cy.get(cesc2("#/bi1_input")).should("be.checked"); - cy.get(cesc2("#/bi2_input")).should("be.checked"); - cy.get(cesc2("#/bi3_input")).should("be.checked"); - cy.get(cesc2("#/bi4_input")).should("be.checked"); - - cy.get(cesc2("#/bi1a")).should("have.text", "true"); - cy.get(cesc2("#/bi2a")).should("have.text", "true"); - cy.get(cesc2("#/bi3a")).should("have.text", "true"); - cy.get(cesc2("#/bi4a")).should("have.text", "true"); - - cy.get(cesc2("#/bi1changed")).should("have.text", "true"); - cy.get(cesc2("#/bi2changed")).should("have.text", "false"); - cy.get(cesc2("#/bi3changed")).should("have.text", "false"); - cy.get(cesc2("#/bi4changed")).should("have.text", "false"); - - cy.log("clicking second marks only second as changed"); - - cy.get(cesc2("#/bi2")).click(); - - cy.get(cesc2("#/bi1_input")).should("be.checked"); - cy.get(cesc2("#/bi2_input")).should("not.be.checked"); - cy.get(cesc2("#/bi3_input")).should("be.checked"); - cy.get(cesc2("#/bi4_input")).should("not.be.checked"); - - cy.get(cesc2("#/bi1a")).should("have.text", "true"); - cy.get(cesc2("#/bi2a")).should("have.text", "false"); - cy.get(cesc2("#/bi3a")).should("have.text", "true"); - cy.get(cesc2("#/bi4a")).should("have.text", "false"); - - cy.get(cesc2("#/bi1changed")).should("have.text", "true"); - cy.get(cesc2("#/bi2changed")).should("have.text", "true"); - cy.get(cesc2("#/bi3changed")).should("have.text", "false"); - cy.get(cesc2("#/bi4changed")).should("have.text", "false"); - - cy.log("clicking third and fourth"); - - cy.get(cesc2("#/bi3")).click(); - cy.get(cesc2("#/bi4")).click(); - - cy.get(cesc2("#/bi1_input")).should("not.be.checked"); - cy.get(cesc2("#/bi2_input")).should("be.checked"); - cy.get(cesc2("#/bi3_input")).should("not.be.checked"); - cy.get(cesc2("#/bi4_input")).should("be.checked"); - - cy.get(cesc2("#/bi1a")).should("have.text", "false"); - cy.get(cesc2("#/bi2a")).should("have.text", "true"); - cy.get(cesc2("#/bi3a")).should("have.text", "false"); - cy.get(cesc2("#/bi4a")).should("have.text", "true"); - - cy.get(cesc2("#/bi1changed")).should("have.text", "true"); - cy.get(cesc2("#/bi2changed")).should("have.text", "true"); - cy.get(cesc2("#/bi3changed")).should("have.text", "true"); - cy.get(cesc2("#/bi4changed")).should("have.text", "true"); - - cy.log("reload"); - cy.reload(); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - }, - "*", - ); - }); - - cy.get(cesc2("#/bi1_input")).should("not.be.checked"); - cy.get(cesc2("#/bi2_input")).should("be.checked"); - cy.get(cesc2("#/bi3_input")).should("not.be.checked"); - cy.get(cesc2("#/bi4_input")).should("be.checked"); - - cy.get(cesc2("#/bi1a")).should("have.text", "false"); - cy.get(cesc2("#/bi2a")).should("have.text", "true"); - cy.get(cesc2("#/bi3a")).should("have.text", "false"); - cy.get(cesc2("#/bi4a")).should("have.text", "true"); - - cy.get(cesc2("#/bi1changed")).should("have.text", "false"); - cy.get(cesc2("#/bi2changed")).should("have.text", "false"); - cy.get(cesc2("#/bi3changed")).should("have.text", "false"); - cy.get(cesc2("#/bi4changed")).should("have.text", "false"); - - cy.log("clicking third marks first and third as changed"); - - cy.get(cesc2("#/bi3")).click(); - - cy.get(cesc2("#/bi1_input")).should("be.checked"); - cy.get(cesc2("#/bi2_input")).should("be.checked"); - cy.get(cesc2("#/bi3_input")).should("be.checked"); - cy.get(cesc2("#/bi4_input")).should("be.checked"); - - cy.get(cesc2("#/bi1a")).should("have.text", "true"); - cy.get(cesc2("#/bi2a")).should("have.text", "true"); - cy.get(cesc2("#/bi3a")).should("have.text", "true"); - cy.get(cesc2("#/bi4a")).should("have.text", "true"); - - cy.get(cesc2("#/bi1changed")).should("have.text", "true"); - cy.get(cesc2("#/bi2changed")).should("have.text", "false"); - cy.get(cesc2("#/bi3changed")).should("have.text", "true"); - cy.get(cesc2("#/bi4changed")).should("have.text", "false"); - - cy.log("clicking fourth marks only second and fourth as changed"); - - cy.get(cesc2("#/bi4")).click(); - - cy.get(cesc2("#/bi1_input")).should("be.checked"); - cy.get(cesc2("#/bi2_input")).should("not.be.checked"); - cy.get(cesc2("#/bi3_input")).should("be.checked"); - cy.get(cesc2("#/bi4_input")).should("not.be.checked"); - - cy.get(cesc2("#/bi1a")).should("have.text", "true"); - cy.get(cesc2("#/bi2a")).should("have.text", "false"); - cy.get(cesc2("#/bi3a")).should("have.text", "true"); - cy.get(cesc2("#/bi4a")).should("have.text", "false"); - - cy.get(cesc2("#/bi1changed")).should("have.text", "true"); - cy.get(cesc2("#/bi2changed")).should("have.text", "true"); - cy.get(cesc2("#/bi3changed")).should("have.text", "true"); - cy.get(cesc2("#/bi4changed")).should("have.text", "true"); - - cy.log("clicking first and second"); - - cy.get(cesc2("#/bi1")).click(); - cy.get(cesc2("#/bi2")).click(); - - cy.get(cesc2("#/bi1_input")).should("not.be.checked"); - cy.get(cesc2("#/bi2_input")).should("be.checked"); - cy.get(cesc2("#/bi3_input")).should("not.be.checked"); - cy.get(cesc2("#/bi4_input")).should("be.checked"); - - cy.get(cesc2("#/bi1a")).should("have.text", "false"); - cy.get(cesc2("#/bi2a")).should("have.text", "true"); - cy.get(cesc2("#/bi3a")).should("have.text", "false"); - cy.get(cesc2("#/bi4a")).should("have.text", "true"); - - cy.get(cesc2("#/bi1changed")).should("have.text", "true"); - cy.get(cesc2("#/bi2changed")).should("have.text", "true"); - cy.get(cesc2("#/bi3changed")).should("have.text", "true"); - cy.get(cesc2("#/bi4changed")).should("have.text", "true"); - }); }); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/callaction.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/callaction.cy.js deleted file mode 100644 index a59fd5636..000000000 --- a/packages/test-cypress/cypress/e2e/tagSpecific/callaction.cy.js +++ /dev/null @@ -1,2942 +0,0 @@ -import { cesc, cesc2 } from "@doenet/utils"; - -describe("CallAction Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("resample random numbers", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

- -

-

Sum: - - - $s - -

- `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let numbers, - sum = 0; - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - numbers = text.split(",").map(Number); - expect(numbers.length).eq(5); - for (let [ind, num] of numbers.entries()) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - sum += num * 10 ** ind; - } - }); - cy.get(cesc("#\\/sum")) - .invoke("text") - .then((text) => { - let sum2 = Number(text); - expect(sum2).eq(sum); - }); - - // main purpose of sum is to make sure wait until recalculation has occured - cy.get(cesc("#\\/rs_button")) - .click() - .then(() => { - cy.get(cesc("#\\/sum")).should("not.contain", sum.toString()); - }); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2.length).eq(5); - for (let num of numbers2) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - expect(numbers2).not.eqls(numbers); - }); - }); - - it("add and delete points", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -
- The graphs - - (1,2) - - - $g{name="g2"} -
- - $theGraphs{name="theGraphs2"} - -

points from graph:

- - - (3,4) - - - - -

$bi.value{assignNames="b"}

- `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/p1")).should("contain.text", "(1,2)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g1 = stateVariables["/theGraphs/g"]; - let g2 = stateVariables["/theGraphs/g2"]; - let g3 = stateVariables["/theGraphs2/g"]; - let g4 = stateVariables["/theGraphs2/g2"]; - let gs = [g1, g2, g3, g4]; - - for (let g of gs) { - expect(g.stateValues.graphicalDescendants.length).eq(1); - } - }); - - cy.get(cesc("#\\/addPoint_button")).click(); - - cy.get(cesc("#\\/p2")).should("contain.text", "(3,4)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g1 = stateVariables["/theGraphs/g"]; - let g2 = stateVariables["/theGraphs/g2"]; - let g3 = stateVariables["/theGraphs2/g"]; - let g4 = stateVariables["/theGraphs2/g2"]; - let gs = [g1, g2, g3, g4]; - - for (let g of gs) { - let pointNames = g.stateValues.graphicalDescendants.map( - (x) => x.componentName, - ); - expect(pointNames.length).eq(2); - expect(stateVariables[pointNames[0]].stateValues.xs).eqls([ - 1, 2, - ]); - expect(stateVariables[pointNames[1]].stateValues.xs).eqls([ - 3, 4, - ]); - } - - await win.callAction1({ - actionName: "movePoint", - componentName: - g1.stateValues.graphicalDescendants[1].componentName, - args: { x: -2, y: 5 }, - }); - }); - - cy.get(cesc("#\\/p2")).should("contain.text", "(−2,5)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g1 = stateVariables["/theGraphs/g"]; - let g2 = stateVariables["/theGraphs/g2"]; - let g3 = stateVariables["/theGraphs2/g"]; - let g4 = stateVariables["/theGraphs2/g2"]; - let gs = [g1, g2, g3, g4]; - - for (let g of gs) { - let pointNames = g.stateValues.graphicalDescendants.map( - (x) => x.componentName, - ); - expect(stateVariables[pointNames[1]].stateValues.xs).eqls([ - -2, 5, - ]); - } - }); - - cy.get(cesc("#\\/addPoint_button")).click(); - - cy.get(cesc("#\\/p3")).should("contain.text", "(3,4)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g1 = stateVariables["/theGraphs/g"]; - let g2 = stateVariables["/theGraphs/g2"]; - let g3 = stateVariables["/theGraphs2/g"]; - let g4 = stateVariables["/theGraphs2/g2"]; - let gs = [g1, g2, g3, g4]; - - for (let g of gs) { - let pointNames = g.stateValues.graphicalDescendants.map( - (x) => x.componentName, - ); - expect(pointNames.length).eq(3); - expect(stateVariables[pointNames[0]].stateValues.xs).eqls([ - 1, 2, - ]); - expect(stateVariables[pointNames[1]].stateValues.xs).eqls([ - -2, 5, - ]); - expect(stateVariables[pointNames[2]].stateValues.xs).eqls([ - 3, 4, - ]); - } - - await win.callAction1({ - actionName: "movePoint", - componentName: - g2.stateValues.graphicalDescendants[2].componentName, - args: { x: 7, y: -9 }, - }); - }); - - cy.get(cesc("#\\/p3")).should("contain.text", "(7,−9)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g1 = stateVariables["/theGraphs/g"]; - let g2 = stateVariables["/theGraphs/g2"]; - let g3 = stateVariables["/theGraphs2/g"]; - let g4 = stateVariables["/theGraphs2/g2"]; - let gs = [g1, g2, g3, g4]; - - for (let g of gs) { - let pointNames = g.stateValues.graphicalDescendants.map( - (x) => x.componentName, - ); - expect(stateVariables[pointNames[2]].stateValues.xs).eqls([ - 7, -9, - ]); - } - }); - - cy.get(cesc("#\\/deletePoint_button")).click(); - - cy.get(cesc("#\\/p3")).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g1 = stateVariables["/theGraphs/g"]; - let g2 = stateVariables["/theGraphs/g2"]; - let g3 = stateVariables["/theGraphs2/g"]; - let g4 = stateVariables["/theGraphs2/g2"]; - let gs = [g1, g2, g3, g4]; - - for (let g of gs) { - let pointNames = g.stateValues.graphicalDescendants.map( - (x) => x.componentName, - ); - expect(pointNames.length).eq(2); - expect(stateVariables[pointNames[0]].stateValues.xs).eqls([ - 1, 2, - ]); - expect(stateVariables[pointNames[1]].stateValues.xs).eqls([ - -2, 5, - ]); - } - - await win.callAction1({ - actionName: "movePoint", - componentName: - g3.stateValues.graphicalDescendants[1].componentName, - args: { x: 1, y: 0 }, - }); - }); - - cy.get(cesc("#\\/p2")).should("contain.text", "(1,0)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g1 = stateVariables["/theGraphs/g"]; - let g2 = stateVariables["/theGraphs/g2"]; - let g3 = stateVariables["/theGraphs2/g"]; - let g4 = stateVariables["/theGraphs2/g2"]; - let gs = [g1, g2, g3, g4]; - - for (let g of gs) { - let pointNames = g.stateValues.graphicalDescendants.map( - (x) => x.componentName, - ); - expect(stateVariables[pointNames[1]].stateValues.xs).eqls([ - 1, 0, - ]); - } - }); - - cy.get(cesc("#\\/deletePoint_button")).click(); - - cy.get(cesc("#\\/p2")).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g1 = stateVariables["/theGraphs/g"]; - let g2 = stateVariables["/theGraphs/g2"]; - let g3 = stateVariables["/theGraphs2/g"]; - let g4 = stateVariables["/theGraphs2/g2"]; - let gs = [g1, g2, g3, g4]; - - for (let g of gs) { - let pointNames = g.stateValues.graphicalDescendants.map( - (x) => x.componentName, - ); - expect(pointNames.length).eq(1); - expect(stateVariables[pointNames[0]].stateValues.xs).eqls([ - 1, 2, - ]); - } - }); - - cy.get(cesc("#\\/deletePoint_button")).click(); - - // since nothing happens, we wait for core to respond to booleaninput - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/b")).should("have.text", "true"); - - cy.get(cesc("#\\/p1")).should("contain.text", "(1,2)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g1 = stateVariables["/theGraphs/g"]; - let g2 = stateVariables["/theGraphs/g2"]; - let g3 = stateVariables["/theGraphs2/g"]; - let g4 = stateVariables["/theGraphs2/g2"]; - let gs = [g1, g2, g3, g4]; - - for (let g of gs) { - let pointNames = g.stateValues.graphicalDescendants.map( - (x) => x.componentName, - ); - expect(pointNames.length).eq(1); - expect(stateVariables[pointNames[0]].stateValues.xs).eqls([ - 1, 2, - ]); - } - }); - - cy.get(cesc("#\\/addPoint_button")).click(); - - cy.get(cesc("#\\/p2")).should("contain.text", "(3,4)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g1 = stateVariables["/theGraphs/g"]; - let g2 = stateVariables["/theGraphs/g2"]; - let g3 = stateVariables["/theGraphs2/g"]; - let g4 = stateVariables["/theGraphs2/g2"]; - let gs = [g1, g2, g3, g4]; - - for (let g of gs) { - let pointNames = g.stateValues.graphicalDescendants.map( - (x) => x.componentName, - ); - expect(pointNames.length).eq(2); - expect(stateVariables[pointNames[0]].stateValues.xs).eqls([ - 1, 2, - ]); - expect(stateVariables[pointNames[1]].stateValues.xs).eqls([ - 3, 4, - ]); - } - }); - }); - - it("chained actions", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

-

- -

- - - (1,2) - - -

points from graph:

- - - - (3,4) - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/addPoint_button")).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g = stateVariables["/g"]; - - expect(g.stateValues.graphicalDescendants.length).eq(1); - - let numbers; - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - numbers = text.split(",").map(Number); - expect(numbers.length).eq(5); - for (let num of numbers) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - }); - - cy.get(cesc("#\\/rs_button")).click(); - - cy.get(cesc("#\\/p2")).should("contain.text", "(3,4"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g = stateVariables["/g"]; - - let pointNames = g.stateValues.graphicalDescendants.map( - (x) => x.componentName, - ); - expect(pointNames.length).eq(2); - expect(stateVariables[pointNames[0]].stateValues.xs).eqls([ - 1, 2, - ]); - expect(stateVariables[pointNames[1]].stateValues.xs).eqls([ - 3, 4, - ]); - - await win.callAction1({ - actionName: "movePoint", - componentName: pointNames[1], - args: { x: -2, y: 5 }, - }); - }); - - cy.get(cesc("#\\/p2")).should("contain.text", "(−2,5)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g = stateVariables["/g"]; - - let pointNames = g.stateValues.graphicalDescendants.map( - (x) => x.componentName, - ); - expect(stateVariables[pointNames[1]].stateValues.xs).eqls([ - -2, 5, - ]); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2.length).eq(5); - for (let num of numbers2) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - expect(numbers2).not.eqls(numbers); - }); - }); - }); - }); - - it("chained actions, unnecessary $", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

-

- -

- - - (1,2) - - -

points from graph:

- - - - (3,4) - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/addPoint_button")).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g = stateVariables["/g"]; - - expect(g.stateValues.graphicalDescendants.length).eq(1); - - let numbers; - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - numbers = text.split(",").map(Number); - expect(numbers.length).eq(5); - for (let num of numbers) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - }); - - cy.get(cesc("#\\/rs_button")).click(); - - cy.get(cesc("#\\/p2")).should("contain.text", "(3,4"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g = stateVariables["/g"]; - - let pointNames = g.stateValues.graphicalDescendants.map( - (x) => x.componentName, - ); - expect(pointNames.length).eq(2); - expect(stateVariables[pointNames[0]].stateValues.xs).eqls([ - 1, 2, - ]); - expect(stateVariables[pointNames[1]].stateValues.xs).eqls([ - 3, 4, - ]); - - await win.callAction1({ - actionName: "movePoint", - componentName: pointNames[1], - args: { x: -2, y: 5 }, - }); - }); - - cy.get(cesc("#\\/p2")).should("contain.text", "(−2,5)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g = stateVariables["/g"]; - - let pointNames = g.stateValues.graphicalDescendants.map( - (x) => x.componentName, - ); - expect(stateVariables[pointNames[1]].stateValues.xs).eqls([ - -2, 5, - ]); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2.length).eq(5); - for (let num of numbers2) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - expect(numbers2).not.eqls(numbers); - }); - }); - }); - }); - - it("chained actions, inside map", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load\ - - for (let ind = 1; ind <= 2; ind++) { - cy.get(cesc(`#\\/set${ind}\\/addPoint_button`)).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g = stateVariables[`/set${ind}/g`]; - - expect(g.stateValues.graphicalDescendants.length).eq(1); - - let numbers; - - cy.get(cesc(`#\\/set${ind}\\/nums`)) - .invoke("text") - .then((text) => { - numbers = text.split(",").map(Number); - expect(numbers.length).eq(5); - for (let num of numbers) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - }); - - cy.get(cesc(`#\\/set${ind}\\/rs_button`)).click(); - - cy.get(cesc(`#\\/set${ind}\\/p2`)).should( - "contain.text", - "(3,4", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g = stateVariables[`/set${ind}/g`]; - - let pointNames = g.stateValues.graphicalDescendants.map( - (x) => x.componentName, - ); - expect(pointNames.length).eq(2); - expect(stateVariables[pointNames[0]].stateValues.xs).eqls([ - 1, 2, - ]); - expect(stateVariables[pointNames[1]].stateValues.xs).eqls([ - 3, 4, - ]); - - await win.callAction1({ - actionName: "movePoint", - componentName: pointNames[1], - args: { x: -2, y: 5 }, - }); - }); - - cy.get(cesc(`#\\/set${ind}\\/p2`)).should( - "contain.text", - "(−2,5)", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g = stateVariables[`/set${ind}/g`]; - - let pointNames = g.stateValues.graphicalDescendants.map( - (x) => x.componentName, - ); - expect(stateVariables[pointNames[1]].stateValues.xs).eqls([ - -2, 5, - ]); - - cy.get(cesc(`#\\/set${ind}\\/nums`)) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2.length).eq(5); - for (let num of numbers2) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - expect(numbers2).not.eqls(numbers); - }); - }); - }); - } - }); - - it("chained actions on multiple sources", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

-

- -

- -

1

-

- -

- - - (1,2) - - -

points from graph:

- - - - (3,4) - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/addPoint")).should("not.exist"); - - let numbers; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g = stateVariables["/g"]; - - expect(g.stateValues.graphicalDescendants.length).eq(1); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - numbers = text.split(",").map(Number); - expect(numbers.length).eq(5); - for (let num of numbers) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - }); - cy.get(cesc("#\\/n")).should("have.text", "1"); - }); - - cy.get(cesc("#\\/rs_button")).click(); - - cy.get(cesc("#\\/p2")).should("contain.text", "(3,4"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g = stateVariables["/g"]; - - let pointNames = g.stateValues.graphicalDescendants.map( - (x) => x.componentName, - ); - expect(pointNames.length).eq(2); - expect(stateVariables[pointNames[0]].stateValues.xs).eqls([1, 2]); - expect(stateVariables[pointNames[1]].stateValues.xs).eqls([3, 4]); - - await win.callAction1({ - actionName: "movePoint", - componentName: pointNames[1], - args: { x: -2, y: 5 }, - }); - }); - - cy.get(cesc("#\\/p2")).should("contain.text", "(−2,5)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g = stateVariables["/g"]; - - let pointNames = g.stateValues.graphicalDescendants.map( - (x) => x.componentName, - ); - expect(stateVariables[pointNames[1]].stateValues.xs).eqls([-2, 5]); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2.length).eq(5); - for (let num of numbers2) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - expect(numbers2).not.eqls(numbers); - }); - - cy.get(cesc("#\\/n")).should("have.text", "1"); - }); - - cy.get(cesc("#\\/in_button")).click(); - - cy.get(cesc("#\\/p3")).should("contain.text", "(3,4"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g = stateVariables["/g"]; - - let pointNames = g.stateValues.graphicalDescendants.map( - (x) => x.componentName, - ); - expect(pointNames.length).eq(3); - expect(stateVariables[pointNames[0]].stateValues.xs).eqls([1, 2]); - expect(stateVariables[pointNames[1]].stateValues.xs).eqls([-2, 5]); - expect(stateVariables[pointNames[2]].stateValues.xs).eqls([3, 4]); - - await win.callAction1({ - actionName: "movePoint", - componentName: pointNames[2], - args: { x: 7, y: -9 }, - }); - }); - - cy.get(cesc("#\\/p3")).should("contain.text", "(7,−9)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g = stateVariables["/g"]; - - let pointNames = g.stateValues.graphicalDescendants.map( - (x) => x.componentName, - ); - expect(stateVariables[pointNames[2]].stateValues.xs).eqls([7, -9]); - - cy.get(cesc("#\\/n")).should("have.text", "2"); - }); - }); - - it("action based on trigger", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (-1,2) - - $P.coords{assignNames="P2"} - -

-

- -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let numbers; - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - numbers = text.split(",").map(Number); - expect(numbers.length).eq(5); - for (let num of numbers) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - }); - - cy.get(cesc("#\\/P2")).should("contain.text", "(−1,2)"); - - cy.get(cesc("#\\/rs")).should("not.exist"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -1, y: -7 }, - }); - - cy.get(cesc("#\\/P2")).should("contain.text", "(−1,−7)"); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 3, y: -4 }, - }); - cy.get(cesc("#\\/P2")).should("contain.text", "(3,−4)"); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 1, y: 7 }, - }); - cy.get(cesc("#\\/P2")).should("contain.text", "(1,7)"); - - cy.waitUntil(() => - cy - .get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - if (numbers2.length !== 5) { - return false; - } - let foundChange = false; - for (let [i, num] of numbers2.entries()) { - if (!Number.isInteger(num) || num < 1 || num > 6) { - return false; - } - if (num !== numbers[i]) { - foundChange = true; - } - } - if (!foundChange) { - return false; - } - numbers = numbers2; - return true; - }), - ); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 5, y: 9 }, - }); - - cy.get(cesc("#\\/P2")).should("contain.text", "(5,9)"); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -3, y: 4 }, - }); - - cy.get(cesc("#\\/P2")).should("contain.text", "(−3,4)"); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -6, y: 5 }, - }); - - cy.get(cesc("#\\/P2")).should("contain.text", "(−6,5)"); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 4, y: 2 }, - }); - - cy.get(cesc("#\\/P2")).should("contain.text", "(4,2)"); - - cy.waitUntil(() => - cy - .get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - if (numbers2.length !== 5) { - return false; - } - let foundChange = false; - for (let [i, num] of numbers2.entries()) { - if (!Number.isInteger(num) || num < 1 || num > 6) { - return false; - } - if (num !== numbers[i]) { - foundChange = true; - } - } - if (!foundChange) { - return false; - } - numbers = numbers2; - return true; - }), - ); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 9, y: 7 }, - }); - - cy.get(cesc("#\\/P2")).should("contain.text", "(9,7)"); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - }); - }); - - it("action triggered when click", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (-1,2) - - $P.coords{assignNames="P2"} - -

-

- -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let numbers; - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - numbers = text.split(",").map(Number); - expect(numbers.length).eq(5); - for (let num of numbers) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - }); - - cy.get(cesc("#\\/P2")).should("contain.text", "(−1,2)"); - - cy.get(cesc("#\\/rs")).should("not.exist"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 3, y: -4 }, - }); - cy.get(cesc("#\\/P2")).should("contain.text", "(3,−4)"); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "pointClicked", - componentName: "/P", - args: { name: "/P" }, - }); - - cy.waitUntil(() => - cy - .get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - if (numbers2.length !== 5) { - return false; - } - let foundChange = false; - for (let [i, num] of numbers2.entries()) { - if (!Number.isInteger(num) || num < 1 || num > 6) { - return false; - } - if (num !== numbers[i]) { - foundChange = true; - } - } - if (!foundChange) { - return false; - } - numbers = numbers2; - return true; - }), - ); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 5, y: 9 }, - }); - - cy.get(cesc("#\\/P2")).should("contain.text", "(5,9)"); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "pointClicked", - componentName: "/P", - args: { name: "/P" }, - }); - - cy.waitUntil(() => - cy - .get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - if (numbers2.length !== 5) { - return false; - } - let foundChange = false; - for (let [i, num] of numbers2.entries()) { - if (!Number.isInteger(num) || num < 1 || num > 6) { - return false; - } - if (num !== numbers[i]) { - foundChange = true; - } - } - if (!foundChange) { - return false; - } - numbers = numbers2; - return true; - }), - ); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 9, y: 7 }, - }); - - cy.get(cesc("#\\/P2")).should("contain.text", "(9,7)"); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - }); - }); - - it("action triggered when click, inside template creating random names", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - for (let ind = 0; ind < 2; ind++) { - let templateName = - stateVariables["/_map1"].replacements[ind].componentName; - - let tReps = stateVariables[templateName].replacements; - let graphName = tReps[1].componentName; - let copyName = tReps[3].componentName; - let numsAnchor = "#" + cesc2(tReps[5].componentName); - - let PName = - stateVariables[graphName].activeChildren[0].componentName; - let P2Anchor = - "#" + - cesc2( - stateVariables[copyName].replacements[0].componentName, - ); - - let numbers; - - cy.get(numsAnchor) - .invoke("text") - .then((text) => { - numbers = text.split(",").map(Number); - expect(numbers.length).eq(5); - for (let num of numbers) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - }); - - cy.get(P2Anchor).should("contain.text", "(−1,2)"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: PName, - args: { x: 3, y: -4 }, - }); - cy.get(P2Anchor).should("contain.text", "(3,−4)"); - - cy.get(numsAnchor) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "pointClicked", - componentName: PName, - args: { name: PName }, - }); - - cy.waitUntil(() => - cy - .get(numsAnchor) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - if (numbers2.length !== 5) { - return false; - } - let foundChange = false; - for (let [i, num] of numbers2.entries()) { - if ( - !Number.isInteger(num) || - num < 1 || - num > 6 - ) { - return false; - } - if (num !== numbers[i]) { - foundChange = true; - } - } - if (!foundChange) { - return false; - } - numbers = numbers2; - return true; - }), - ); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: PName, - args: { x: 5, y: 9 }, - }); - - cy.get(P2Anchor).should("contain.text", "(5,9)"); - - cy.get(numsAnchor) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "pointClicked", - componentName: PName, - args: { name: PName }, - }); - - cy.waitUntil(() => - cy - .get(numsAnchor) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - if (numbers2.length !== 5) { - return false; - } - let foundChange = false; - for (let [i, num] of numbers2.entries()) { - if ( - !Number.isInteger(num) || - num < 1 || - num > 6 - ) { - return false; - } - if (num !== numbers[i]) { - foundChange = true; - } - } - if (!foundChange) { - return false; - } - numbers = numbers2; - return true; - }), - ); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: PName, - args: { x: 9, y: 7 }, - }); - - cy.get(P2Anchor).should("contain.text", "(9,7)"); - - cy.get(numsAnchor) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - }); - } - }); - }); - - it("action triggered when object focused", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (-1,2) - - $P.coords{assignNames="P2"} - -

-

- -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let numbers; - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - numbers = text.split(",").map(Number); - expect(numbers.length).eq(5); - for (let num of numbers) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - }); - - cy.get(cesc("#\\/P2")).should("contain.text", "(−1,2)"); - - cy.get(cesc("#\\/rs")).should("not.exist"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 3, y: -4 }, - }); - cy.get(cesc("#\\/P2")).should("contain.text", "(3,−4)"); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "pointFocused", - componentName: "/P", - args: { name: "/P" }, - }); - - cy.waitUntil(() => - cy - .get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - if (numbers2.length !== 5) { - return false; - } - let foundChange = false; - for (let [i, num] of numbers2.entries()) { - if (!Number.isInteger(num) || num < 1 || num > 6) { - return false; - } - if (num !== numbers[i]) { - foundChange = true; - } - } - if (!foundChange) { - return false; - } - numbers = numbers2; - return true; - }), - ); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 5, y: 9 }, - }); - - cy.get(cesc("#\\/P2")).should("contain.text", "(5,9)"); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "pointFocused", - componentName: "/P", - args: { name: "/P" }, - }); - - cy.waitUntil(() => - cy - .get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - if (numbers2.length !== 5) { - return false; - } - let foundChange = false; - for (let [i, num] of numbers2.entries()) { - if (!Number.isInteger(num) || num < 1 || num > 6) { - return false; - } - if (num !== numbers[i]) { - foundChange = true; - } - } - if (!foundChange) { - return false; - } - numbers = numbers2; - return true; - }), - ); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 9, y: 7 }, - }); - - cy.get(cesc("#\\/P2")).should("contain.text", "(9,7)"); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - }); - }); - - it("chained updates based on trigger", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (-1,2) - - $P.coords{assignNames="P2"} - -

-

- -

- - - - (3,4) - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/P2")).should("contain.text", "(−1,2)"); - cy.get(cesc("#\\/rs")).should("not.exist"); - cy.get(cesc("#\\/addPoint")).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.stateValues.graphicalDescendants.length).eq(1); - }); - - let numbers; - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - numbers = text.split(",").map(Number); - expect(numbers.length).eq(5); - for (let num of numbers) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -1, y: -7 }, - }); - }); - - cy.get(cesc("#\\/P2")).should("contain.text", "(−1,−7)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.stateValues.graphicalDescendants.length).eq(1); - }); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 3, y: -4 }, - }); - }); - - cy.get(cesc("#\\/P2")).should("contain.text", "(3,−4)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.stateValues.graphicalDescendants.length).eq(1); - }); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 1, y: 7 }, - }); - }); - - cy.get(cesc("#\\/P2")).should("contain.text", "(1,7)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.stateValues.graphicalDescendants.length).eq(2); - }); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2.length).eq(5); - for (let num of numbers2) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - expect(numbers2).not.eqls(numbers); - numbers = numbers2; - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 5, y: 9 }, - }); - }); - - cy.get(cesc("#\\/P2")).should("contain.text", "(5,9)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.stateValues.graphicalDescendants.length).eq(2); - }); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -3, y: 4 }, - }); - }); - - cy.get(cesc("#\\/P2")).should("contain.text", "(−3,4)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.stateValues.graphicalDescendants.length).eq(2); - }); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -6, y: 5 }, - }); - }); - cy.get(cesc("#\\/P2")).should("contain.text", "(−6,5)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.stateValues.graphicalDescendants.length).eq(2); - }); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 4, y: 2 }, - }); - }); - - cy.get(cesc("#\\/P2")).should("contain.text", "(4,2)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.stateValues.graphicalDescendants.length).eq(3); - }); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2.length).eq(5); - for (let num of numbers2) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - expect(numbers2).not.eqls(numbers); - numbers = numbers2; - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 9, y: 7 }, - }); - }); - - cy.get(cesc("#\\/P2")).should("contain.text", "(9,7)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.stateValues.graphicalDescendants.length).eq(3); - }); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - }); - - it("triggerWhen supercedes chaining", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (-1,2) - - - $P.coords{assignNames="P2"} - -

-

- -

- - - - (3,4) - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/P2")).should("contain.text", "(−1,2)"); - cy.get(cesc("#\\/rs")).should("not.exist"); - cy.get(cesc("#\\/addPoint")).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.stateValues.graphicalDescendants.length).eq(1); - }); - - let numbers; - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - numbers = text.split(",").map(Number); - expect(numbers.length).eq(5); - for (let num of numbers) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -1, y: -7 }, - }); - }); - - cy.get(cesc("#\\/P2")).should("contain.text", "(−1,−7)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.stateValues.graphicalDescendants.length).eq(1); - }); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2.length).eq(5); - for (let num of numbers2) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - expect(numbers2).not.eqls(numbers); - numbers = numbers2; - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 3, y: -4 }, - }); - }); - - cy.get(cesc("#\\/P2")).should("contain.text", "(3,−4)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.stateValues.graphicalDescendants.length).eq(1); - }); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 1, y: 7 }, - }); - }); - - cy.get(cesc("#\\/P2")).should("contain.text", "(1,7)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.stateValues.graphicalDescendants.length).eq(2); - }); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 5, y: 9 }, - }); - }); - - cy.get(cesc("#\\/P2")).should("contain.text", "(5,9)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.stateValues.graphicalDescendants.length).eq(2); - }); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -3, y: -4 }, - }); - }); - - cy.get(cesc("#\\/P2")).should("contain.text", "(−3,−4)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.stateValues.graphicalDescendants.length).eq(2); - }); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2.length).eq(5); - for (let num of numbers2) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - expect(numbers2).not.eqls(numbers); - numbers = numbers2; - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -6, y: -5 }, - }); - }); - - cy.get(cesc("#\\/P2")).should("contain.text", "(−6,−5)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.stateValues.graphicalDescendants.length).eq(2); - }); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 4, y: 2 }, - }); - }); - - cy.get(cesc("#\\/P2")).should("contain.text", "(4,2)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.stateValues.graphicalDescendants.length).eq(3); - }); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 9, y: 7 }, - }); - }); - - cy.get(cesc("#\\/P2")).should("contain.text", "(9,7)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.stateValues.graphicalDescendants.length).eq(3); - }); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - }); - - it("triggerSet", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - (1,2) - - -

points from graph:

- -

- - - - - - - - - (3,4) - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/rs")).should("not.exist"); - cy.get(cesc("#\\/addPoint")).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.stateValues.graphicalDescendants.length).eq(1); - }); - - let numbers; - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - numbers = text.split(",").map(Number); - expect(numbers.length).eq(5); - for (let num of numbers) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - }); - - cy.get(cesc("#\\/tset_button")).click(); - - cy.get(cesc("#\\/p2")).should("contain.text", "(3,4)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g = stateVariables["/g"]; - - let pointNames = g.stateValues.graphicalDescendants.map( - (x) => x.componentName, - ); - expect(pointNames.length).eq(2); - expect(stateVariables[pointNames[0]].stateValues.xs).eqls([1, 2]); - expect(stateVariables[pointNames[1]].stateValues.xs).eqls([3, 4]); - - await win.callAction1({ - actionName: "movePoint", - componentName: pointNames[1], - args: { x: -2, y: 5 }, - }); - }); - - cy.get(cesc("#\\/p2")).should("contain.text", "(−2,5)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g = stateVariables["/g"]; - - let pointNames = g.stateValues.graphicalDescendants.map( - (x) => x.componentName, - ); - expect(stateVariables[pointNames[1]].stateValues.xs).eqls([-2, 5]); - }); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2.length).eq(5); - for (let num of numbers2) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - expect(numbers2).not.eqls(numbers); - }); - }); - - it("triggerSet and chain to callAction", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - (1,2) - - -

points from graph:

- -

- -

Enter x: x

- - - - - - - - - (3,4) - - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/rs")).should("not.exist"); - cy.get(cesc("#\\/addPoint")).should("not.exist"); - cy.get(cesc("#\\/sub")).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g = stateVariables["/g"]; - - let mathinputName = - stateVariables["/ans"].stateValues.inputChildren[0] - .componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); - let mathinputCorrectAnchor = cesc2( - "#" + mathinputName + "_correct", - ); - let mathinputIncorrectAnchor = cesc2( - "#" + mathinputName + "_incorrect", - ); - let mathinputPartialAnchor = cesc2( - "#" + mathinputName + "_partial", - ); - - cy.get(mathinputAnchor).type(`x`, { force: true }); - - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); - - expect(g.stateValues.graphicalDescendants.length).eq(1); - - let numbers; - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - numbers = text.split(",").map(Number); - expect(numbers.length).eq(5); - for (let num of numbers) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - }); - - cy.get(cesc("#\\/tset_button")).click(); - - cy.get(cesc("#\\/p2")).should("contain.text", "(3,4)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g = stateVariables["/g"]; - - let pointNames = g.stateValues.graphicalDescendants.map( - (x) => x.componentName, - ); - expect(pointNames.length).eq(2); - expect(stateVariables[pointNames[0]].stateValues.xs).eqls([ - 1, 2, - ]); - expect(stateVariables[pointNames[1]].stateValues.xs).eqls([ - 3, 4, - ]); - - await win.callAction1({ - actionName: "movePoint", - componentName: pointNames[1], - args: { x: -2, y: 5 }, - }); - }); - - cy.get(cesc("#\\/p2")).should("contain.text", "(−2,5)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g = stateVariables["/g"]; - - let pointNames = g.stateValues.graphicalDescendants.map( - (x) => x.componentName, - ); - expect(stateVariables[pointNames[1]].stateValues.xs).eqls([ - -2, 5, - ]); - }); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2.length).eq(5); - for (let num of numbers2) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - expect(numbers2).not.eqls(numbers); - }); - - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("be.visible"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - cy.get(mathinputPartialAnchor).should("not.exist"); - }); - }); - - it("chaining with updateValue", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

-

- -

- - - (1,2) - - -

points from graph:

- - - - (3,4) - - -

Count: 1

- - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/addPoint")).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.stateValues.graphicalDescendants.length).eq(1); - }); - - let numbers; - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - numbers = text.split(",").map(Number); - expect(numbers.length).eq(5); - for (let num of numbers) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - }); - cy.get(cesc("#\\/n")).should("have.text", "1"); - - cy.get(cesc("#\\/rs_button")).click(); - - cy.get(cesc("#\\/p2")).should("contain.text", "(3,4)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g = stateVariables["/g"]; - - let pointNames = g.stateValues.graphicalDescendants.map( - (x) => x.componentName, - ); - expect(pointNames.length).eq(2); - expect(stateVariables[pointNames[0]].stateValues.xs).eqls([1, 2]); - expect(stateVariables[pointNames[1]].stateValues.xs).eqls([3, 4]); - - await win.callAction1({ - actionName: "movePoint", - componentName: pointNames[1], - args: { x: -2, y: 5 }, - }); - }); - - cy.get(cesc("#\\/p2")).should("contain.text", "(−2,5)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let g = stateVariables["/g"]; - - let pointNames = g.stateValues.graphicalDescendants.map( - (x) => x.componentName, - ); - expect(stateVariables[pointNames[1]].stateValues.xs).eqls([-2, 5]); - }); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2.length).eq(5); - for (let num of numbers2) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - expect(numbers2).not.eqls(numbers); - }); - - cy.get(cesc("#\\/n")).should("have.text", "2"); - }); - - it("math in label", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

- `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/rs")).should("contain.text", "Hi ∑5i=1xi"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/rs"].stateValues.label).eq( - "Hi \\(\\sum_{i=1}^5x_i\\)", - ); - }); - }); - - it("label is name", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

- `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/resample_numbers")).should( - "contain.text", - "resample numbers", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/resample_numbers"].stateValues.label).eq( - "resample numbers", - ); - }); - }); - - it("case insensitive action name", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

Sum: - - - $s - -

- `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let numbers, - sum = 0; - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - numbers = text.split(",").map(Number); - expect(numbers.length).eq(5); - for (let [ind, num] of numbers.entries()) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - sum += num * 10 ** ind; - } - }); - cy.get(cesc("#\\/sum")) - .invoke("text") - .then((text) => { - let sum2 = Number(text); - expect(sum2).eq(sum); - }); - - // main purpose of sum is to make sure wait until recalculation has occured - cy.get(cesc("#\\/rs_button")) - .click() - .then(() => { - cy.get(cesc("#\\/sum")).should("not.contain", sum.toString()); - }); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2.length).eq(5); - for (let num of numbers2) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - expect(numbers2).not.eqls(numbers); - }); - }); - - it("callaction in graph", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - (3,4) - - - - (-3,-4) - - - -

Anchor 1 coordinates: $callaction1.anchor

-

Anchor 2 coordinates: $callaction2.anchor

-

Change anchor 1 coordinates:

-

Change anchor 2 coordinates:

-

Position from anchor 1: $callaction1.positionFromAnchor

-

Position from anchor 2: $callaction2.positionFromAnchor

-

Change position from anchor 1 - - upperRight - upperLeft - lowerRight - lowerLeft - left - right - top - bottom - center - -

-

Change position from anchor 2 - - upperRight - upperLeft - lowerRight - lowerLeft - left - right - top - bottom - center - -

-

Draggable 1: $draggable1

-

Draggable 2: $draggable2

-

Change draggable 1

-

Change draggable 2

-

Disabled 1: $disabled1

-

Disabled 2: $disabled2

-

Change disabled 1

-

Change disabled 2

-

Fixed 1: $fixed1

-

Fixed 2: $fixed2

-

Change fixed 1

-

Change fixed 2

-

FixLocation 1: $fixLocation1

-

FixLocation 2: $fixLocation2

-

Change fixLocation 1

-

Change fixLocation 2

-

- - `, - }, - "*", - ); - }); - - // TODO: how to click on the buttons and test if they are disabled? - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,3)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,0)"); - - cy.get(cesc("#\\/pPositionFromAnchor1")).should( - "have.text", - "Position from anchor 1: upperright", - ); - cy.get(cesc("#\\/pPositionFromAnchor2")).should( - "have.text", - "Position from anchor 2: center", - ); - cy.get(cesc("#\\/positionFromAnchor1")).should("have.value", "1"); - cy.get(cesc("#\\/positionFromAnchor2")).should("have.value", "9"); - cy.get(cesc("#\\/pDraggable1")).should( - "have.text", - "Draggable 1: true", - ); - cy.get(cesc("#\\/pDraggable2")).should( - "have.text", - "Draggable 2: true", - ); - - cy.log("move callactions by dragging"); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveButton", - componentName: "/callaction1", - args: { x: -2, y: 3 }, - }); - win.callAction1({ - actionName: "moveButton", - componentName: "/callaction2", - args: { x: 4, y: -5 }, - }); - }); - - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow").should( - "contain.text", - "(4,−5)", - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−2,3)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(4,−5)"); - - cy.log("move callactions by entering coordinates"); - - cy.get(cesc("#\\/anchorCoords1") + " textarea").type( - "{home}{shift+end}{backspace}(6,7){enter}", - { force: true }, - ); - cy.get(cesc("#\\/anchorCoords2") + " textarea").type( - "{home}{shift+end}{backspace}(8,9){enter}", - { force: true }, - ); - - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow").should( - "contain.text", - "(8,9)", - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(6,7)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(8,9)"); - - cy.log("change position from anchor"); - cy.get(cesc("#\\/positionFromAnchor1")).select("lowerLeft"); - cy.get(cesc("#\\/positionFromAnchor2")).select("lowerRight"); - - cy.get(cesc("#\\/pPositionFromAnchor1")).should( - "have.text", - "Position from anchor 1: lowerleft", - ); - cy.get(cesc("#\\/pPositionFromAnchor2")).should( - "have.text", - "Position from anchor 2: lowerright", - ); - - cy.log("make not draggable"); - - cy.get(cesc("#\\/draggable1")).click(); - cy.get(cesc("#\\/draggable2")).click(); - cy.get(cesc("#\\/pDraggable1")).should( - "have.text", - "Draggable 1: false", - ); - cy.get(cesc("#\\/pDraggable2")).should( - "have.text", - "Draggable 2: false", - ); - - cy.log("cannot move callactions by dragging"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveButton", - componentName: "/callaction1", - args: { x: -10, y: -9 }, - }); - win.callAction1({ - actionName: "moveButton", - componentName: "/callaction2", - args: { x: -8, y: -7 }, - }); - }); - - // since nothing will change, wait for boolean input to change to know core has responded - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/b")).should("have.text", "true"); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(6,7)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(8,9)"); - - cy.log("make draggable again"); - - cy.get(cesc("#\\/draggable1")).click(); - cy.get(cesc("#\\/draggable2")).click(); - cy.get(cesc("#\\/pDraggable1")).should( - "have.text", - "Draggable 1: true", - ); - cy.get(cesc("#\\/pDraggable2")).should( - "have.text", - "Draggable 2: true", - ); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveButton", - componentName: "/callaction1", - args: { x: -10, y: -9 }, - }); - win.callAction1({ - actionName: "moveButton", - componentName: "/callaction2", - args: { x: -8, y: -7 }, - }); - }); - - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow").should( - "contain.text", - "(−8,−7)", - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−10,−9)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−8,−7)"); - - cy.log("fix location"); - - cy.get(cesc("#\\/fixLocation1")).click(); - cy.get(cesc("#\\/fixLocation2")).click(); - cy.get(cesc("#\\/pFixLocation1")).should( - "have.text", - "FixLocation 1: true", - ); - cy.get(cesc("#\\/pFixLocation2")).should( - "have.text", - "FixLocation 2: true", - ); - - cy.log("can change coordinates entering coordinates only for button 1"); - - cy.get(cesc("#\\/anchorCoords2") + " textarea").type( - "{home}{shift+end}{backspace}(3,4){enter}", - { force: true }, - ); - cy.get(cesc("#\\/anchorCoords1") + " textarea").type( - "{home}{shift+end}{backspace}(1,2){enter}", - { force: true }, - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow").should( - "contain.text", - "(1,2)", - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−8,−7)"); - - cy.log("cannot move callactions by dragging"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveButton", - componentName: "/callaction1", - args: { x: 4, y: 6 }, - }); - win.callAction1({ - actionName: "moveButton", - componentName: "/callaction2", - args: { x: 7, y: 8 }, - }); - }); - - // since nothing will change, wait for boolean input to change to know core has responded - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/b")).should("have.text", "false"); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−8,−7)"); - - cy.log("can change position from anchor only for button 1"); - cy.get(cesc("#\\/positionFromAnchor2")).select("bottom"); - cy.get(cesc("#\\/positionFromAnchor1")).select("top"); - - cy.get(cesc("#\\/pPositionFromAnchor1")).should( - "have.text", - "Position from anchor 1: top", - ); - cy.get(cesc("#\\/pPositionFromAnchor2")).should( - "have.text", - "Position from anchor 2: lowerright", - ); - - cy.log("can change disabled attribute"); - cy.get(cesc("#\\/disabled1")).click(); - cy.get(cesc("#\\/disabled2")).click(); - cy.get(cesc("#\\/pDisabled1")).should("have.text", "Disabled 1: false"); - cy.get(cesc("#\\/pDisabled2")).should("have.text", "Disabled 2: true"); - - cy.log("make completely fixed"); - cy.get(cesc("#\\/fixed1")).click(); - cy.get(cesc("#\\/fixed2")).click(); - cy.get(cesc("#\\/pFixed1")).should("have.text", "Fixed 1: true"); - cy.get(cesc("#\\/pFixed2")).should("have.text", "Fixed 2: true"); - - cy.log("can change coordinates entering coordinates only for button 1"); - - cy.get(cesc("#\\/anchorCoords2") + " textarea").type( - "{home}{shift+end}{backspace}(7,8){enter}", - { force: true }, - ); - cy.get(cesc("#\\/anchorCoords1") + " textarea").type( - "{home}{shift+end}{backspace}(5,6){enter}", - { force: true }, - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow").should( - "contain.text", - "(5,6)", - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(5,6)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−8,−7)"); - - cy.log("can change position from anchor only for button 1"); - cy.get(cesc("#\\/positionFromAnchor2")).select("left"); - cy.get(cesc("#\\/positionFromAnchor1")).select("right"); - - cy.get(cesc("#\\/pPositionFromAnchor1")).should( - "have.text", - "Position from anchor 1: right", - ); - cy.get(cesc("#\\/pPositionFromAnchor2")).should( - "have.text", - "Position from anchor 2: lowerright", - ); - - cy.log("can change disabled attribute only for button 1"); - cy.get(cesc("#\\/disabled2")).click(); - cy.get(cesc("#\\/disabled1")).click(); - cy.get(cesc("#\\/pDisabled1")).should("have.text", "Disabled 1: true"); - cy.get(cesc("#\\/pDisabled2")).should("have.text", "Disabled 2: true"); - }); -}); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/collect.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/collect.cy.js deleted file mode 100644 index a2ac3177c..000000000 --- a/packages/test-cypress/cypress/e2e/tagSpecific/collect.cy.js +++ /dev/null @@ -1,5780 +0,0 @@ -import { cesc, cesc2 } from "@doenet/utils"; - -function nInDOM(n) { - if (n < 0) { - return `−${Math.abs(n)}`; - } else { - return String(n); - } -} - -describe("Collect Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("collect points from graphs", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - (-3,1) - (-7,5) - - - - $_point1{name="p1a"} - (4,2) - - (, - ) - - - - - - - - -

Coordinates of points:

-

x-coordinates of points:

-

x-coordinates of points via a copy:

-

x-coordinates of points via extract:

-

Average of y-coordinates of points:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let x1 = -3, - y1 = 1; - let x2 = -7, - y2 = 5; - let x3 = 4, - y3 = 2; - - let coords1Text = ("(" + x1 + "," + y1 + ")").replace(/-/g, "−"); - let coords2Text = ("(" + x2 + "," + y2 + ")").replace(/-/g, "−"); - let coords3Text = ("(" + x3 + "," + y3 + ")").replace(/-/g, "−"); - let coords2tText = ("(" + y2 + "," + x2 + ")").replace(/-/g, "−"); - - let meany = (y1 + y2 + y1 + y3 + x2) / 5; - - cy.get(cesc("#\\/c1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(coords1Text); - }); - cy.get(cesc("#\\/c2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(coords2Text); - }); - cy.get(cesc("#\\/c3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(coords1Text); - }); - cy.get(cesc("#\\/c4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(coords3Text); - }); - cy.get(cesc("#\\/c5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(coords2tText); - }); - - cy.get(cesc("#\\/x1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(x1).replace(/-/, "−")); - }); - cy.get(cesc("#\\/x2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(x2).replace(/-/, "−")); - }); - cy.get(cesc("#\\/x3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(x1).replace(/-/, "−")); - }); - cy.get(cesc("#\\/x4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(x3).replace(/-/, "−")); - }); - cy.get(cesc("#\\/x5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(y2).replace(/-/, "−")); - }); - - cy.get(cesc("#\\/xc1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(x1).replace(/-/, "−")); - }); - cy.get(cesc("#\\/xc2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(x2).replace(/-/, "−")); - }); - cy.get(cesc("#\\/xc3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(x1).replace(/-/, "−")); - }); - cy.get(cesc("#\\/xc4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(x3).replace(/-/, "−")); - }); - cy.get(cesc("#\\/xc5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(y2).replace(/-/, "−")); - }); - - cy.get(cesc("#\\/xe1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(x1).replace(/-/, "−")); - }); - cy.get(cesc("#\\/xe2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(x2).replace(/-/, "−")); - }); - cy.get(cesc("#\\/xe3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(x1).replace(/-/, "−")); - }); - cy.get(cesc("#\\/xe4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(x3).replace(/-/, "−")); - }); - cy.get(cesc("#\\/xe5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(y2).replace(/-/, "−")); - }); - - cy.get(cesc("#\\/mean")) - .find(".mjx-mrow") - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(meany).replace(/-/, "−")); - }); - - cy.window().then(async (win) => { - let xs = [x1, x2, x1, x3, y2]; - let ys = [y1, y2, y1, y3, x2]; - let stateVariables = await win.returnAllStateVariables1(); - for (let i = 0; i < 5; i++) { - expect(stateVariables[`/q${i + 1}`].stateValues.xs[0]).eq( - xs[i], - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[1]).eq( - ys[i], - ); - expect(stateVariables[`/qa${i + 1}`].stateValues.xs[0]).eq( - xs[i], - ); - expect(stateVariables[`/qa${i + 1}`].stateValues.xs[1]).eq( - ys[i], - ); - expect(stateVariables[`/c${i + 1}`].stateValues.value).eqls([ - "vector", - xs[i], - ys[i], - ]); - expect(stateVariables[`/x${i + 1}`].stateValues.value).eq( - xs[i], - ); - expect(stateVariables[`/xc${i + 1}`].stateValues.value).eq( - xs[i], - ); - expect(stateVariables[`/xe${i + 1}`].stateValues.value).eq( - xs[i], - ); - expect(stateVariables[`/y${i + 1}`].stateValues.value).eq( - ys[i], - ); - } - expect(stateVariables["/mean"].stateValues.value).eq(meany); - }); - - cy.log("move point 1"); - cy.window().then(async (win) => { - x1 = -8; - y1 = 6; - let xs = [x1, x2, x1, x3, y2]; - let ys = [y1, y2, y1, y3, x2]; - meany = (y1 + y2 + y1 + y3 + x2) / 5; - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: x1, y: y1 }, - }); - - cy.get(cesc("#\\/c1")).should( - "contain.text", - `(${nInDOM(x1)},${nInDOM(y1)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - for (let i = 0; i < 5; i++) { - expect(stateVariables[`/q${i + 1}`].stateValues.xs[0]).eq( - xs[i], - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[1]).eq( - ys[i], - ); - expect(stateVariables[`/qa${i + 1}`].stateValues.xs[0]).eq( - xs[i], - ); - expect(stateVariables[`/qa${i + 1}`].stateValues.xs[1]).eq( - ys[i], - ); - expect(stateVariables[`/c${i + 1}`].stateValues.value).eqls( - ["vector", xs[i], ys[i]], - ); - expect(stateVariables[`/x${i + 1}`].stateValues.value).eq( - xs[i], - ); - expect(stateVariables[`/xc${i + 1}`].stateValues.value).eq( - xs[i], - ); - expect(stateVariables[`/xe${i + 1}`].stateValues.value).eq( - xs[i], - ); - expect(stateVariables[`/y${i + 1}`].stateValues.value).eq( - ys[i], - ); - } - expect(stateVariables["/mean"].stateValues.value).eq(meany); - }); - }); - - cy.log("move point 1 via copy"); - cy.window().then(async (win) => { - x1 = 2; - y1 = 0; - let xs = [x1, x2, x1, x3, y2]; - let ys = [y1, y2, y1, y3, x2]; - meany = (y1 + y2 + y1 + y3 + x2) / 5; - - await win.callAction1({ - actionName: "movePoint", - componentName: "/p1a", - args: { x: x1, y: y1 }, - }); - - cy.get(cesc("#\\/c1")).should( - "contain.text", - `(${nInDOM(x1)},${nInDOM(y1)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let i = 0; i < 5; i++) { - expect(stateVariables[`/q${i + 1}`].stateValues.xs[0]).eq( - xs[i], - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[1]).eq( - ys[i], - ); - expect(stateVariables[`/qa${i + 1}`].stateValues.xs[0]).eq( - xs[i], - ); - expect(stateVariables[`/qa${i + 1}`].stateValues.xs[1]).eq( - ys[i], - ); - expect(stateVariables[`/c${i + 1}`].stateValues.value).eqls( - ["vector", xs[i], ys[i]], - ); - expect(stateVariables[`/x${i + 1}`].stateValues.value).eq( - xs[i], - ); - expect(stateVariables[`/xc${i + 1}`].stateValues.value).eq( - xs[i], - ); - expect(stateVariables[`/xe${i + 1}`].stateValues.value).eq( - xs[i], - ); - expect(stateVariables[`/y${i + 1}`].stateValues.value).eq( - ys[i], - ); - } - expect(stateVariables["/mean"].stateValues.value).eq(meany); - }); - }); - - cy.log("move point 2"); - cy.window().then(async (win) => { - x2 = 4; - y2 = 8; - let xs = [x1, x2, x1, x3, y2]; - let ys = [y1, y2, y1, y3, x2]; - meany = (y1 + y2 + y1 + y3 + x2) / 5; - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point2", - args: { x: x2, y: y2 }, - }); - - cy.get(cesc("#\\/c2")).should( - "contain.text", - `(${nInDOM(x2)},${nInDOM(y2)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - for (let i = 0; i < 5; i++) { - expect(stateVariables[`/q${i + 1}`].stateValues.xs[0]).eq( - xs[i], - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[1]).eq( - ys[i], - ); - expect(stateVariables[`/qa${i + 1}`].stateValues.xs[0]).eq( - xs[i], - ); - expect(stateVariables[`/qa${i + 1}`].stateValues.xs[1]).eq( - ys[i], - ); - expect(stateVariables[`/c${i + 1}`].stateValues.value).eqls( - ["vector", xs[i], ys[i]], - ); - expect(stateVariables[`/x${i + 1}`].stateValues.value).eq( - xs[i], - ); - expect(stateVariables[`/xc${i + 1}`].stateValues.value).eq( - xs[i], - ); - expect(stateVariables[`/xe${i + 1}`].stateValues.value).eq( - xs[i], - ); - expect(stateVariables[`/y${i + 1}`].stateValues.value).eq( - ys[i], - ); - } - expect(stateVariables["/mean"].stateValues.value).eq(meany); - }); - }); - - cy.log("move flipped point 2"); - cy.window().then(async (win) => { - x2 = -1; - y2 = -3; - let xs = [x1, x2, x1, x3, y2]; - let ys = [y1, y2, y1, y3, x2]; - meany = (y1 + y2 + y1 + y3 + x2) / 5; - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point4", - args: { x: y2, y: x2 }, - }); - - cy.get(cesc("#\\/c2")).should( - "contain.text", - `(${nInDOM(x2)},${nInDOM(y2)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - for (let i = 0; i < 5; i++) { - expect(stateVariables[`/q${i + 1}`].stateValues.xs[0]).eq( - xs[i], - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[1]).eq( - ys[i], - ); - expect(stateVariables[`/qa${i + 1}`].stateValues.xs[0]).eq( - xs[i], - ); - expect(stateVariables[`/qa${i + 1}`].stateValues.xs[1]).eq( - ys[i], - ); - expect(stateVariables[`/c${i + 1}`].stateValues.value).eqls( - ["vector", xs[i], ys[i]], - ); - expect(stateVariables[`/x${i + 1}`].stateValues.value).eq( - xs[i], - ); - expect(stateVariables[`/xc${i + 1}`].stateValues.value).eq( - xs[i], - ); - expect(stateVariables[`/xe${i + 1}`].stateValues.value).eq( - xs[i], - ); - expect(stateVariables[`/y${i + 1}`].stateValues.value).eq( - ys[i], - ); - } - expect(stateVariables["/mean"].stateValues.value).eq(meany); - }); - }); - - cy.log("move point 3"); - cy.window().then(async (win) => { - x3 = -5; - y3 = 9; - let xs = [x1, x2, x1, x3, y2]; - let ys = [y1, y2, y1, y3, x2]; - meany = (y1 + y2 + y1 + y3 + x2) / 5; - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point3", - args: { x: x3, y: y3 }, - }); - - cy.get(cesc("#\\/c4")).should( - "contain.text", - `(${nInDOM(x3)},${nInDOM(y3)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - for (let i = 0; i < 5; i++) { - expect(stateVariables[`/q${i + 1}`].stateValues.xs[0]).eq( - xs[i], - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[1]).eq( - ys[i], - ); - expect(stateVariables[`/qa${i + 1}`].stateValues.xs[0]).eq( - xs[i], - ); - expect(stateVariables[`/qa${i + 1}`].stateValues.xs[1]).eq( - ys[i], - ); - expect(stateVariables[`/c${i + 1}`].stateValues.value).eqls( - ["vector", xs[i], ys[i]], - ); - expect(stateVariables[`/x${i + 1}`].stateValues.value).eq( - xs[i], - ); - expect(stateVariables[`/xc${i + 1}`].stateValues.value).eq( - xs[i], - ); - expect(stateVariables[`/xe${i + 1}`].stateValues.value).eq( - xs[i], - ); - expect(stateVariables[`/y${i + 1}`].stateValues.value).eq( - ys[i], - ); - } - expect(stateVariables["/mean"].stateValues.value).eq(meany); - }); - }); - }); - - it("collect dynamic points from graphs", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - y=x/3 - - - - - - - - - - - - - - - -

y-coordinates of points: - -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(3); - expect( - stateVariables["/_collect1"].stateValues.collectedComponents - .length, - ).eq(3); - expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(3); - expect( - stateVariables["/_collect2"].stateValues.collectedComponents - .length, - ).eq(6); - expect( - stateVariables["/_collect3"].stateValues.collectedComponents - .length, - ).eq(6); - - for (let i = 0; i < 3; i++) { - let x = i + 1; - expect(stateVariables[`/p${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/p${i + 1}`].stateValues.xs[1]).eq( - 2 * x, - ); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1]).eq( - 2 * x, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[1]).eq( - 3 * x, - ); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[1]).eq( - 2 * x, - ); - expect(stateVariables[`/r${i + 4}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/r${i + 4}`].stateValues.xs[1]).eq( - 3 * x, - ); - expect(stateVariables[`/y${i + 1}`].stateValues.value).eq( - 2 * x, - ); - expect(stateVariables[`/y${i + 4}`].stateValues.value).eq( - 3 * x, - ); - } - }); - - cy.log("increase number of points"); - cy.get(cesc("#\\/length") + " textarea").type( - `{end}{backspace}5{enter}`, - { - force: true, - }, - ); - - cy.get(cesc("#\\/y10")).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(5); - expect( - stateVariables["/_collect1"].stateValues.collectedComponents - .length, - ).eq(5); - expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(5); - expect( - stateVariables["/_collect2"].stateValues.collectedComponents - .length, - ).eq(10); - expect( - stateVariables["/_collect3"].stateValues.collectedComponents - .length, - ).eq(10); - - for (let i = 0; i < 5; i++) { - let x = i + 1; - expect(stateVariables[`/p${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/p${i + 1}`].stateValues.xs[1]).eq( - 2 * x, - ); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1]).eq( - 2 * x, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[1]).eq( - 3 * x, - ); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[1]).eq( - 2 * x, - ); - expect(stateVariables[`/r${i + 6}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/r${i + 6}`].stateValues.xs[1]).eq( - 3 * x, - ); - expect(stateVariables[`/y${i + 1}`].stateValues.value).eq( - 2 * x, - ); - expect(stateVariables[`/y${i + 6}`].stateValues.value).eq( - 3 * x, - ); - } - }); - - cy.log("change multiple"); - cy.get(cesc("#\\/mult") + " textarea").type( - `{end}{backspace}0.5{enter}`, - { - force: true, - }, - ); - - cy.get(cesc("#\\/y10")).should("contain.text", "3.75"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(5); - expect( - stateVariables["/_collect1"].stateValues.collectedComponents - .length, - ).eq(5); - expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(5); - expect( - stateVariables["/_collect2"].stateValues.collectedComponents - .length, - ).eq(10); - expect( - stateVariables["/_collect3"].stateValues.collectedComponents - .length, - ).eq(10); - - for (let i = 0; i < 5; i++) { - let x = i + 1; - expect(stateVariables[`/p${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/p${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[1]).eq( - 0.75 * x, - ); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/r${i + 6}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/r${i + 6}`].stateValues.xs[1]).eq( - 0.75 * x, - ); - expect(stateVariables[`/y${i + 1}`].stateValues.value).eq( - 0.5 * x, - ); - expect(stateVariables[`/y${i + 6}`].stateValues.value).eq( - 0.75 * x, - ); - } - }); - - cy.log("decrease number of points"); - cy.get(cesc("#\\/length") + " textarea").type( - `{end}{backspace}1{enter}`, - { - force: true, - }, - ); - - cy.get(cesc("#\\/y10")).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(1); - expect( - stateVariables["/_collect1"].stateValues.collectedComponents - .length, - ).eq(1); - expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(1); - expect( - stateVariables["/_collect2"].stateValues.collectedComponents - .length, - ).eq(2); - expect( - stateVariables["/_collect3"].stateValues.collectedComponents - .length, - ).eq(2); - - for (let i = 0; i < 1; i++) { - let x = i + 1; - expect(stateVariables[`/p${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/p${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[1]).eq( - 0.75 * x, - ); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/r${i + 2}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/r${i + 2}`].stateValues.xs[1]).eq( - 0.75 * x, - ); - expect(stateVariables[`/y${i + 1}`].stateValues.value).eq( - 0.5 * x, - ); - expect(stateVariables[`/y${i + 2}`].stateValues.value).eq( - 0.75 * x, - ); - } - }); - - cy.log("increase number of points back to 4"); - cy.get(cesc("#\\/length") + " textarea").type( - `{end}{backspace}4{enter}`, - { - force: true, - }, - ); - - cy.get(cesc("#\\/y8")).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(4); - expect( - stateVariables["/_collect1"].stateValues.collectedComponents - .length, - ).eq(4); - expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(4); - expect( - stateVariables["/_collect2"].stateValues.collectedComponents - .length, - ).eq(8); - expect( - stateVariables["/_collect3"].stateValues.collectedComponents - .length, - ).eq(8); - - for (let i = 0; i < 4; i++) { - let x = i + 1; - expect(stateVariables[`/p${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/p${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[1]).eq( - 0.75 * x, - ); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/r${i + 5}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/r${i + 5}`].stateValues.xs[1]).eq( - 0.75 * x, - ); - expect(stateVariables[`/y${i + 1}`].stateValues.value).eq( - 0.5 * x, - ); - expect(stateVariables[`/y${i + 5}`].stateValues.value).eq( - 0.75 * x, - ); - } - }); - - cy.log("increase number of points to 6"); - cy.get(cesc("#\\/length") + " textarea").type( - `{end}{backspace}6{enter}`, - { - force: true, - }, - ); - - cy.get(cesc("#\\/y12")).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(6); - expect( - stateVariables["/_collect1"].stateValues.collectedComponents - .length, - ).eq(6); - expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(6); - expect( - stateVariables["/_collect2"].stateValues.collectedComponents - .length, - ).eq(12); - expect( - stateVariables["/_collect3"].stateValues.collectedComponents - .length, - ).eq(12); - - for (let i = 0; i < 6; i++) { - let x = i + 1; - expect(stateVariables[`/p${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/p${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[1]).eq( - 0.75 * x, - ); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/r${i + 7}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/r${i + 7}`].stateValues.xs[1]).eq( - 0.75 * x, - ); - expect(stateVariables[`/y${i + 1}`].stateValues.value).eq( - 0.5 * x, - ); - expect(stateVariables[`/y${i + 7}`].stateValues.value).eq( - 0.75 * x, - ); - } - }); - }); - - it("collect dynamic points from groups", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -
- - - - - - y=x/3 - - - - - - - - - -
- - - - - -

y-coordinates of points: - -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(3); - expect( - stateVariables["/_collect1"].stateValues.collectedComponents - .length, - ).eq(3); - expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(3); - expect( - stateVariables["/_collect2"].stateValues.collectedComponents - .length, - ).eq(6); - expect( - stateVariables["/_collect3"].stateValues.collectedComponents - .length, - ).eq(6); - - for (let i = 0; i < 3; i++) { - let x = i + 1; - expect(stateVariables[`/p${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/p${i + 1}`].stateValues.xs[1]).eq( - 2 * x, - ); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1]).eq( - 2 * x, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[1]).eq( - 3 * x, - ); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[1]).eq( - 2 * x, - ); - expect(stateVariables[`/r${i + 4}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/r${i + 4}`].stateValues.xs[1]).eq( - 3 * x, - ); - expect(stateVariables[`/y${i + 1}`].stateValues.value).eq( - 2 * x, - ); - expect(stateVariables[`/y${i + 4}`].stateValues.value).eq( - 3 * x, - ); - } - }); - - cy.log("increase number of points"); - cy.get(cesc("#\\/length") + " textarea").type( - `{end}{backspace}5{enter}`, - { - force: true, - }, - ); - - cy.get(cesc("#\\/y10")).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(5); - expect( - stateVariables["/_collect1"].stateValues.collectedComponents - .length, - ).eq(5); - expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(5); - expect( - stateVariables["/_collect2"].stateValues.collectedComponents - .length, - ).eq(10); - expect( - stateVariables["/_collect3"].stateValues.collectedComponents - .length, - ).eq(10); - - for (let i = 0; i < 5; i++) { - let x = i + 1; - expect(stateVariables[`/p${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/p${i + 1}`].stateValues.xs[1]).eq( - 2 * x, - ); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1]).eq( - 2 * x, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[1]).eq( - 3 * x, - ); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[1]).eq( - 2 * x, - ); - expect(stateVariables[`/r${i + 6}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/r${i + 6}`].stateValues.xs[1]).eq( - 3 * x, - ); - expect(stateVariables[`/y${i + 1}`].stateValues.value).eq( - 2 * x, - ); - expect(stateVariables[`/y${i + 6}`].stateValues.value).eq( - 3 * x, - ); - } - }); - - cy.log("change multiple"); - cy.get(cesc("#\\/mult") + " textarea").type( - `{end}{backspace}0.5{enter}`, - { - force: true, - }, - ); - - cy.get(cesc("#\\/y10")).should("contain.text", "3.75"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(5); - expect( - stateVariables["/_collect1"].stateValues.collectedComponents - .length, - ).eq(5); - expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(5); - expect( - stateVariables["/_collect2"].stateValues.collectedComponents - .length, - ).eq(10); - expect( - stateVariables["/_collect3"].stateValues.collectedComponents - .length, - ).eq(10); - - for (let i = 0; i < 5; i++) { - let x = i + 1; - expect(stateVariables[`/p${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/p${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[1]).eq( - 0.75 * x, - ); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/r${i + 6}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/r${i + 6}`].stateValues.xs[1]).eq( - 0.75 * x, - ); - expect(stateVariables[`/y${i + 1}`].stateValues.value).eq( - 0.5 * x, - ); - expect(stateVariables[`/y${i + 6}`].stateValues.value).eq( - 0.75 * x, - ); - } - }); - - cy.log("decrease number of points"); - cy.get(cesc("#\\/length") + " textarea").type( - `{end}{backspace}1{enter}`, - { - force: true, - }, - ); - - cy.get(cesc("#\\/y10")).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(1); - expect( - stateVariables["/_collect1"].stateValues.collectedComponents - .length, - ).eq(1); - expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(1); - expect( - stateVariables["/_collect2"].stateValues.collectedComponents - .length, - ).eq(2); - expect( - stateVariables["/_collect3"].stateValues.collectedComponents - .length, - ).eq(2); - - for (let i = 0; i < 1; i++) { - let x = i + 1; - expect(stateVariables[`/p${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/p${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[1]).eq( - 0.75 * x, - ); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/r${i + 2}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/r${i + 2}`].stateValues.xs[1]).eq( - 0.75 * x, - ); - expect(stateVariables[`/y${i + 1}`].stateValues.value).eq( - 0.5 * x, - ); - expect(stateVariables[`/y${i + 2}`].stateValues.value).eq( - 0.75 * x, - ); - } - }); - - cy.log("increase number of points back to 4"); - cy.get(cesc("#\\/length") + " textarea").type( - `{end}{backspace}4{enter}`, - { - force: true, - }, - ); - - cy.get(cesc("#\\/y8")).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(4); - expect( - stateVariables["/_collect1"].stateValues.collectedComponents - .length, - ).eq(4); - expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(4); - expect( - stateVariables["/_collect2"].stateValues.collectedComponents - .length, - ).eq(8); - expect( - stateVariables["/_collect3"].stateValues.collectedComponents - .length, - ).eq(8); - - for (let i = 0; i < 4; i++) { - let x = i + 1; - expect(stateVariables[`/p${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/p${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[1]).eq( - 0.75 * x, - ); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/r${i + 5}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/r${i + 5}`].stateValues.xs[1]).eq( - 0.75 * x, - ); - expect(stateVariables[`/y${i + 1}`].stateValues.value).eq( - 0.5 * x, - ); - expect(stateVariables[`/y${i + 5}`].stateValues.value).eq( - 0.75 * x, - ); - } - }); - - cy.log("increase number of points to 6"); - cy.get(cesc("#\\/length") + " textarea").type( - `{end}{backspace}6{enter}`, - { - force: true, - }, - ); - - cy.get(cesc("#\\/y12")).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(6); - expect( - stateVariables["/_collect1"].stateValues.collectedComponents - .length, - ).eq(6); - expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(6); - expect( - stateVariables["/_collect2"].stateValues.collectedComponents - .length, - ).eq(12); - expect( - stateVariables["/_collect3"].stateValues.collectedComponents - .length, - ).eq(12); - - for (let i = 0; i < 6; i++) { - let x = i + 1; - expect(stateVariables[`/p${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/p${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[1]).eq( - 0.75 * x, - ); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/r${i + 7}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/r${i + 7}`].stateValues.xs[1]).eq( - 0.75 * x, - ); - expect(stateVariables[`/y${i + 1}`].stateValues.value).eq( - 0.5 * x, - ); - expect(stateVariables[`/y${i + 7}`].stateValues.value).eq( - 0.75 * x, - ); - } - }); - }); - - it("collect points and vectors from graphs", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - (-3,1) - (-7,4) - - - - - - (, - ) - - - (, - ) - - - - - - - - - - $_vector1.head{assignNames="h1"} - $_vector2.head{assignNames="h2"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let x1 = -3, - y1 = 1; - let x2 = -7, - y2 = 4; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_point1"].stateValues.coords).eqls([ - "vector", - x1, - y1, - ]); - expect(stateVariables["/_point2"].stateValues.coords).eqls([ - "vector", - x2, - y2, - ]); - expect(stateVariables["/_vector1"].stateValues.tail).eqls([x1, y1]); - expect(stateVariables["/_vector1"].stateValues.head).eqls([x2, y2]); - expect(stateVariables["/_point3"].stateValues.coords).eqls([ - "vector", - y1, - x1, - ]); - expect(stateVariables["/_point4"].stateValues.coords).eqls([ - "vector", - y2, - x2, - ]); - expect(stateVariables["/_vector2"].stateValues.tail).eqls([y1, x1]); - expect(stateVariables["/_vector2"].stateValues.head).eqls([y2, x2]); - expect( - stateVariables["/_collect1"].stateValues.collectedComponents - .length, - ).eq(6); - expect(stateVariables["/v1"].stateValues.coords).eqls([ - "vector", - x1, - y1, - ]); - expect(stateVariables["/v2"].stateValues.coords).eqls([ - "vector", - x2, - y2, - ]); - expect(stateVariables["/v3"].stateValues.tail).eqls([x1, y1]); - expect(stateVariables["/v3"].stateValues.head).eqls([x2, y2]); - expect(stateVariables["/v4"].stateValues.coords).eqls([ - "vector", - y1, - x1, - ]); - expect(stateVariables["/v5"].stateValues.coords).eqls([ - "vector", - y2, - x2, - ]); - expect(stateVariables["/v6"].stateValues.tail).eqls([y1, x1]); - expect(stateVariables["/v6"].stateValues.head).eqls([y2, x2]); - cy.get(cesc("#\\/h1")).should( - "contain.text", - `(${nInDOM(x2)},${nInDOM(y2)})`, - ); - }); - - cy.log("move vector 1 via copy"); - cy.window().then(async (win) => { - x1 = -8; - y1 = 6; - x2 = 3; - y2 = 2; - - win.callAction1({ - actionName: "moveVector", - componentName: "/v3", - args: { tailcoords: [x1, y1], headcoords: [x2, y2] }, - }); - - cy.get(cesc("#\\/h1")).should( - "contain.text", - `(${nInDOM(x2)},${nInDOM(y2)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_point1"].stateValues.coords).eqls([ - "vector", - x1, - y1, - ]); - expect(stateVariables["/_point2"].stateValues.coords).eqls([ - "vector", - x2, - y2, - ]); - expect(stateVariables["/_vector1"].stateValues.tail).eqls([ - x1, - y1, - ]); - expect(stateVariables["/_vector1"].stateValues.head).eqls([ - x2, - y2, - ]); - expect(stateVariables["/_point3"].stateValues.coords).eqls([ - "vector", - y1, - x1, - ]); - expect(stateVariables["/_point4"].stateValues.coords).eqls([ - "vector", - y2, - x2, - ]); - expect(stateVariables["/_vector2"].stateValues.tail).eqls([ - y1, - x1, - ]); - expect(stateVariables["/_vector2"].stateValues.head).eqls([ - y2, - x2, - ]); - expect( - stateVariables["/_collect1"].stateValues.collectedComponents - .length, - ).eq(6); - expect(stateVariables["/v1"].stateValues.coords).eqls([ - "vector", - x1, - y1, - ]); - expect(stateVariables["/v2"].stateValues.coords).eqls([ - "vector", - x2, - y2, - ]); - expect(stateVariables["/v3"].stateValues.tail).eqls([x1, y1]); - expect(stateVariables["/v3"].stateValues.head).eqls([x2, y2]); - expect(stateVariables["/v4"].stateValues.coords).eqls([ - "vector", - y1, - x1, - ]); - expect(stateVariables["/v5"].stateValues.coords).eqls([ - "vector", - y2, - x2, - ]); - expect(stateVariables["/v6"].stateValues.tail).eqls([y1, x1]); - expect(stateVariables["/v6"].stateValues.head).eqls([y2, x2]); - }); - }); - - cy.log("move vector 2 via copy"); - cy.window().then(async (win) => { - x1 = 9; - y1 = 0; - x2 = -7; - y2 = 5; - - win.callAction1({ - actionName: "moveVector", - componentName: "/v6", - args: { tailcoords: [y1, x1], headcoords: [y2, x2] }, - }); - - cy.get(cesc("#\\/h2")).should( - "contain.text", - `(${nInDOM(y2)},${nInDOM(x2)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_point1"].stateValues.coords).eqls([ - "vector", - x1, - y1, - ]); - expect(stateVariables["/_point2"].stateValues.coords).eqls([ - "vector", - x2, - y2, - ]); - expect(stateVariables["/_vector1"].stateValues.tail).eqls([ - x1, - y1, - ]); - expect(stateVariables["/_vector1"].stateValues.head).eqls([ - x2, - y2, - ]); - expect(stateVariables["/_point3"].stateValues.coords).eqls([ - "vector", - y1, - x1, - ]); - expect(stateVariables["/_point4"].stateValues.coords).eqls([ - "vector", - y2, - x2, - ]); - expect(stateVariables["/_vector2"].stateValues.tail).eqls([ - y1, - x1, - ]); - expect(stateVariables["/_vector2"].stateValues.head).eqls([ - y2, - x2, - ]); - expect( - stateVariables["/_collect1"].stateValues.collectedComponents - .length, - ).eq(6); - expect(stateVariables["/v1"].stateValues.coords).eqls([ - "vector", - x1, - y1, - ]); - expect(stateVariables["/v2"].stateValues.coords).eqls([ - "vector", - x2, - y2, - ]); - expect(stateVariables["/v3"].stateValues.tail).eqls([x1, y1]); - expect(stateVariables["/v3"].stateValues.head).eqls([x2, y2]); - expect(stateVariables["/v4"].stateValues.coords).eqls([ - "vector", - y1, - x1, - ]); - expect(stateVariables["/v5"].stateValues.coords).eqls([ - "vector", - y2, - x2, - ]); - expect(stateVariables["/v6"].stateValues.tail).eqls([y1, x1]); - expect(stateVariables["/v6"].stateValues.head).eqls([y2, x2]); - }); - }); - }); - - it("maximum number", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - - y=x/3 - - - - - - - - - - - - - - - -

y-coordinates of points: - -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(5); - expect( - stateVariables["/_collect1"].stateValues.collectedComponents - .length, - ).eq(2); - expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(2); - expect( - stateVariables["/_collect2"].stateValues.collectedComponents - .length, - ).eq(4); - expect( - stateVariables["/_collect3"].stateValues.collectedComponents - .length, - ).eq(2); - - for (let i = 0; i < 5; i++) { - let x = i + 1; - expect(stateVariables[`/p${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/p${i + 1}`].stateValues.xs[1]).eq( - 2 * x, - ); - } - for (let i = 0; i < 2; i++) { - let x = i + 1; - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1]).eq( - 2 * x, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[1]).eq( - 3 * x, - ); - } - for (let i = 0; i < 4; i++) { - let x = i + 1; - expect(stateVariables[`/r${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[1]).eq( - 2 * x, - ); - } - for (let i = 0; i < 2; i++) { - let x = i + 1; - expect(stateVariables[`/y${i + 1}`].stateValues.value).eq( - 2 * x, - ); - } - }); - - cy.log("increase maxnumber"); - cy.get(cesc("#\\/maxnumber") + " textarea").type( - `{end}{backspace}5{enter}`, - { force: true }, - ); - - cy.get(cesc("#\\/y5")).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(5); - expect( - stateVariables["/_collect1"].stateValues.collectedComponents - .length, - ).eq(5); - expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(5); - expect( - stateVariables["/_collect2"].stateValues.collectedComponents - .length, - ).eq(10); - expect( - stateVariables["/_collect3"].stateValues.collectedComponents - .length, - ).eq(5); - - for (let i = 0; i < 5; i++) { - let x = i + 1; - expect(stateVariables[`/p${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/p${i + 1}`].stateValues.xs[1]).eq( - 2 * x, - ); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1]).eq( - 2 * x, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[1]).eq( - 3 * x, - ); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[1]).eq( - 2 * x, - ); - expect(stateVariables[`/r${i + 6}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/r${i + 6}`].stateValues.xs[1]).eq( - 3 * x, - ); - expect(stateVariables[`/y${i + 1}`].stateValues.value).eq( - 2 * x, - ); - //expect(stateVariables[`/y${i + 6}`].stateValues.value).eq(3 * x); - } - }); - - cy.log("increase maxnumber further"); - cy.get(cesc("#\\/maxnumber") + " textarea").type( - `{end}{backspace}10{enter}`, - { force: true }, - ); - - cy.get(cesc("#\\/y10")).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(5); - expect( - stateVariables["/_collect1"].stateValues.collectedComponents - .length, - ).eq(5); - expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(5); - expect( - stateVariables["/_collect2"].stateValues.collectedComponents - .length, - ).eq(10); - expect( - stateVariables["/_collect3"].stateValues.collectedComponents - .length, - ).eq(10); - - for (let i = 0; i < 5; i++) { - let x = i + 1; - expect(stateVariables[`/p${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/p${i + 1}`].stateValues.xs[1]).eq( - 2 * x, - ); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1]).eq( - 2 * x, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[1]).eq( - 3 * x, - ); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[1]).eq( - 2 * x, - ); - expect(stateVariables[`/r${i + 6}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/r${i + 6}`].stateValues.xs[1]).eq( - 3 * x, - ); - expect(stateVariables[`/y${i + 1}`].stateValues.value).eq( - 2 * x, - ); - expect(stateVariables[`/y${i + 6}`].stateValues.value).eq( - 3 * x, - ); - } - }); - - cy.log("change multiple"); - cy.get(cesc("#\\/mult") + " textarea").type( - `{end}{backspace}0.5{enter}`, - { - force: true, - }, - ); - - cy.get(cesc("#\\/y10")).should("contain.text", "3.75"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(5); - expect( - stateVariables["/_collect1"].stateValues.collectedComponents - .length, - ).eq(5); - expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(5); - expect( - stateVariables["/_collect2"].stateValues.collectedComponents - .length, - ).eq(10); - expect( - stateVariables["/_collect3"].stateValues.collectedComponents - .length, - ).eq(10); - - for (let i = 0; i < 5; i++) { - let x = i + 1; - expect(stateVariables[`/p${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/p${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[1]).eq( - 0.75 * x, - ); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/r${i + 6}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/r${i + 6}`].stateValues.xs[1]).eq( - 0.75 * x, - ); - expect(stateVariables[`/y${i + 1}`].stateValues.value).eq( - 0.5 * x, - ); - expect(stateVariables[`/y${i + 6}`].stateValues.value).eq( - 0.75 * x, - ); - } - }); - - cy.log("decrease number of points"); - cy.get(cesc("#\\/length") + " textarea").type( - `{end}{backspace}1{enter}`, - { - force: true, - }, - ); - - cy.get(cesc("#\\/y10")).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(1); - expect( - stateVariables["/_collect1"].stateValues.collectedComponents - .length, - ).eq(1); - expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(1); - expect( - stateVariables["/_collect2"].stateValues.collectedComponents - .length, - ).eq(2); - expect( - stateVariables["/_collect3"].stateValues.collectedComponents - .length, - ).eq(2); - - for (let i = 0; i < 1; i++) { - let x = i + 1; - expect(stateVariables[`/p${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/p${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[1]).eq( - 0.75 * x, - ); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/r${i + 2}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/r${i + 2}`].stateValues.xs[1]).eq( - 0.75 * x, - ); - expect(stateVariables[`/y${i + 1}`].stateValues.value).eq( - 0.5 * x, - ); - expect(stateVariables[`/y${i + 2}`].stateValues.value).eq( - 0.75 * x, - ); - } - }); - - cy.log("increase number of points back to 4"); - cy.get(cesc("#\\/length") + " textarea").type( - `{end}{backspace}4{enter}`, - { - force: true, - }, - ); - - cy.get(cesc("#\\/y4")).should("be.visible"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(4); - expect( - stateVariables["/_collect1"].stateValues.collectedComponents - .length, - ).eq(4); - expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(4); - expect( - stateVariables["/_collect2"].stateValues.collectedComponents - .length, - ).eq(8); - expect( - stateVariables["/_collect3"].stateValues.collectedComponents - .length, - ).eq(8); - - for (let i = 0; i < 4; i++) { - let x = i + 1; - expect(stateVariables[`/p${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/p${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[1]).eq( - 0.75 * x, - ); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/r${i + 5}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/r${i + 5}`].stateValues.xs[1]).eq( - 0.75 * x, - ); - expect(stateVariables[`/y${i + 1}`].stateValues.value).eq( - 0.5 * x, - ); - expect(stateVariables[`/y${i + 5}`].stateValues.value).eq( - 0.75 * x, - ); - } - }); - - cy.log("decrease max number to 3"); - cy.get(cesc("#\\/maxnumber") + " textarea").type( - `{end}{backspace}{backspace}3{enter}`, - { force: true }, - ); - - cy.get(cesc("#\\/y4")).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_map1"].stateValues.numIterates[0]).eq(4); - expect( - stateVariables["/_collect1"].stateValues.collectedComponents - .length, - ).eq(3); - expect(stateVariables["/_map2"].stateValues.numIterates[0]).eq(3); - expect( - stateVariables["/_collect2"].stateValues.collectedComponents - .length, - ).eq(6); - expect( - stateVariables["/_collect3"].stateValues.collectedComponents - .length, - ).eq(3); - - for (let i = 0; i < 4; i++) { - let x = i + 1; - expect(stateVariables[`/p${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/p${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - } - for (let i = 0; i < 3; i++) { - let x = i + 1; - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/pa${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[1]).eq( - 0.75 * x, - ); - } - for (let i = 0; i < 4; i++) { - let x = i + 1; - - expect(stateVariables[`/r${i + 1}`].stateValues.xs[0]).eq(x); - expect(stateVariables[`/r${i + 1}`].stateValues.xs[1]).eq( - 0.5 * x, - ); - } - for (let i = 0; i < 2; i++) { - let x = i + 1; - expect(stateVariables[`/r${i + 5}`].stateValues.xs[0]).eq( - x + 1, - ); - expect(stateVariables[`/r${i + 5}`].stateValues.xs[1]).eq( - 0.75 * x, - ); - } - for (let i = 0; i < 3; i++) { - let x = i + 1; - expect(stateVariables[`/y${i + 1}`].stateValues.value).eq( - 0.5 * x, - ); - } - }); - }); - - it("collect, extract, copy multiple ways", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - aa - -

How many blanks? - -

- -

Enter expressions: - - - - - - -

- -

Inputs collected then, values extracted: -

- -

Copied:

-

Copy aslist:

-

Copy copied: $values1a

-

Copy aslist containing copy: $al1a

-

Copy copied aslist: $al1b

- -

Values collected: -

- -

Copied:

-

Copy aslist:

-

Copy copied: $values2a

-

Copy aslist containing copy: $al2a

-

Copy copied aslist: $al2b

- -

Inputs collected:

- -

Copied:

-

Copy aslist:

-

Copy copied: $cola

-

Copy aslist containing copy: $al3a

-

Copy copied aslist: $al3b

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - cy.get(cesc("#\\/_math1") + " .mjx-mrow").should("contain.text", "a"); - - cy.get(cesc("#\\/p_3e") + " span:nth-of-type(1) textarea").type( - "x{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/p_1") + " > span:nth-of-type(1) .mjx-mrow").should( - "contain.text", - "x", - ); - // cy.get(cesc('#\\/p_original') + ' span:nth-of-type(1) input').should('have.value', 'x'); - - cy.get(cesc("#\\/p_1") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_1a") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_1b") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_1c") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_1d") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_1e") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - - cy.get(cesc("#\\/p_2") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_2a") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_2b") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_2c") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_2d") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_2e") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - - // cy.get(cesc('#\\/p_3') + ' > span:nth-of-type(1) input').should('have.value', 'x'); - // cy.get(cesc('#\\/p_3a') + ' > span:nth-of-type(1) input').should('have.value', 'x'); - // cy.get(cesc('#\\/p_3b') + ' > span:nth-of-type(1) input').should('have.value', 'x'); - // cy.get(cesc('#\\/p_3c') + ' > span:nth-of-type(1) input').should('have.value', 'x'); - // cy.get(cesc('#\\/p_3d') + ' > span:nth-of-type(1) input').should('have.value', 'x'); - // cy.get(cesc('#\\/p_3e') + ' > span:nth-of-type(1) input').should('have.value', 'x'); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}5{enter}", { - force: true, - }); - - cy.get(cesc("#\\/p_original") + " span:nth-of-type(2) textarea") - .type("{end}{backspace}y", { force: true }) - .blur(); - cy.get(cesc("#\\/p_original") + " span:nth-of-type(3) textarea") - .type("{end}{backspace}z", { force: true }) - .blur(); - cy.get(cesc("#\\/p_original") + " span:nth-of-type(4) textarea") - .type("{end}{backspace}u", { force: true }) - .blur(); - cy.get(cesc("#\\/p_original") + " span:nth-of-type(5) textarea") - .type("{end}{backspace}v", { force: true }) - .blur(); - - cy.get(cesc("#\\/p_1") + " > span:nth-of-type(5) .mjx-mrow").should( - "contain.text", - "v", - ); - - // cy.get(cesc('#\\/p_original') + ' > span:nth-of-type(1) input').should('have.value', 'x'); - - cy.get(cesc("#\\/p_1") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_1a") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_1b") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_1c") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_1d") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_1e") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - - cy.get(cesc("#\\/p_2") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_2a") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_2b") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_2c") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_2d") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_2e") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - - // cy.get(cesc('#\\/p_3') + ' > span:nth-of-type(1) input').should('have.value', 'x'); - // cy.get(cesc('#\\/p_3a') + ' > span:nth-of-type(1) input').should('have.value', 'x'); - // cy.get(cesc('#\\/p_3b') + ' > span:nth-of-type(1) input').should('have.value', 'x'); - // cy.get(cesc('#\\/p_3c') + ' > span:nth-of-type(1) input').should('have.value', 'x'); - // cy.get(cesc('#\\/p_3d') + ' > span:nth-of-type(1) input').should('have.value', 'x'); - // cy.get(cesc('#\\/p_3e') + ' > span:nth-of-type(1) input').should('have.value', 'x'); - - // cy.get(cesc('#\\/p_original') + ' > span:nth-of-type(2) input').should('have.value', 'y'); - - cy.get(cesc("#\\/p_1") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/p_1a") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/p_1b") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/p_1c") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/p_1d") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/p_1e") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - - cy.get(cesc("#\\/p_2") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/p_2a") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/p_2b") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/p_2c") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/p_2d") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/p_2e") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - - // cy.get(cesc('#\\/p_3') + ' > span:nth-of-type(2) input').should('have.value', 'y'); - // cy.get(cesc('#\\/p_3a') + ' > span:nth-of-type(2) input').should('have.value', 'y'); - // cy.get(cesc('#\\/p_3b') + ' > span:nth-of-type(2) input').should('have.value', 'y'); - // cy.get(cesc('#\\/p_3c') + ' > span:nth-of-type(2) input').should('have.value', 'y'); - // cy.get(cesc('#\\/p_3d') + ' > span:nth-of-type(2) input').should('have.value', 'y'); - // cy.get(cesc('#\\/p_3e') + ' > span:nth-of-type(2) input').should('have.value', 'y'); - - // cy.get(cesc('#\\/p_original') + ' > span:nth-of-type(3) input').should('have.value', 'z'); - - cy.get(cesc("#\\/p_1") + " > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/p_1a") + " > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/p_1b") + " > span > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/p_1c") + " > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/p_1d") + " > span > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/p_1e") + " > span > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - - cy.get(cesc("#\\/p_2") + " > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/p_2a") + " > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/p_2b") + " > span > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/p_2c") + " > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/p_2d") + " > span > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/p_2e") + " > span > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - - // cy.get(cesc('#\\/p_3') + ' > span:nth-of-type(3) input').should('have.value', 'z'); - // cy.get(cesc('#\\/p_3a') + ' > span:nth-of-type(3) input').should('have.value', 'z'); - // cy.get(cesc('#\\/p_3b') + ' > span:nth-of-type(3) input').should('have.value', 'z'); - // cy.get(cesc('#\\/p_3c') + ' > span:nth-of-type(3) input').should('have.value', 'z'); - // cy.get(cesc('#\\/p_3d') + ' > span:nth-of-type(3) input').should('have.value', 'z'); - // cy.get(cesc('#\\/p_3e') + ' > span:nth-of-type(3) input').should('have.value', 'z'); - - // cy.get(cesc('#\\/p_original') + ' > span:nth-of-type(4) input').should('have.value', 'u'); - - cy.get(cesc("#\\/p_1") + " > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("u"); - }); - cy.get(cesc("#\\/p_1a") + " > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("u"); - }); - cy.get(cesc("#\\/p_1b") + " > span > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("u"); - }); - cy.get(cesc("#\\/p_1c") + " > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("u"); - }); - cy.get(cesc("#\\/p_1d") + " > span > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("u"); - }); - cy.get(cesc("#\\/p_1e") + " > span > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("u"); - }); - - cy.get(cesc("#\\/p_2") + " > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("u"); - }); - cy.get(cesc("#\\/p_2a") + " > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("u"); - }); - cy.get(cesc("#\\/p_2b") + " > span > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("u"); - }); - cy.get(cesc("#\\/p_2c") + " > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("u"); - }); - cy.get(cesc("#\\/p_2d") + " > span > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("u"); - }); - cy.get(cesc("#\\/p_2e") + " > span > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("u"); - }); - - // cy.get(cesc('#\\/p_3') + ' > span:nth-of-type(4) input').should('have.value', 'u'); - // cy.get(cesc('#\\/p_3a') + ' > span:nth-of-type(4) input').should('have.value', 'u'); - // cy.get(cesc('#\\/p_3b') + ' > span:nth-of-type(4) input').should('have.value', 'u'); - // cy.get(cesc('#\\/p_3c') + ' > span:nth-of-type(4) input').should('have.value', 'u'); - // cy.get(cesc('#\\/p_3d') + ' > span:nth-of-type(4) input').should('have.value', 'u'); - // cy.get(cesc('#\\/p_3e') + ' > span:nth-of-type(4) input').should('have.value', 'u'); - - // cy.get(cesc('#\\/p_original') + ' > span:nth-of-type(5) input').should('have.value', 'v'); - - cy.get(cesc("#\\/p_1") + " > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v"); - }); - cy.get(cesc("#\\/p_1a") + " > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v"); - }); - cy.get(cesc("#\\/p_1b") + " > span > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v"); - }); - cy.get(cesc("#\\/p_1c") + " > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v"); - }); - cy.get(cesc("#\\/p_1d") + " > span > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v"); - }); - cy.get(cesc("#\\/p_1e") + " > span > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v"); - }); - - cy.get(cesc("#\\/p_2") + " > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v"); - }); - cy.get(cesc("#\\/p_2a") + " > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v"); - }); - cy.get(cesc("#\\/p_2b") + " > span > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v"); - }); - cy.get(cesc("#\\/p_2c") + " > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v"); - }); - cy.get(cesc("#\\/p_2d") + " > span > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v"); - }); - cy.get(cesc("#\\/p_2e") + " > span > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v"); - }); - - // cy.get(cesc('#\\/p_3') + ' > span:nth-of-type(5) input').should('have.value', 'v'); - // cy.get(cesc('#\\/p_3a') + ' > span:nth-of-type(5) input').should('have.value', 'v'); - // cy.get(cesc('#\\/p_3b') + ' > span:nth-of-type(5) input').should('have.value', 'v'); - // cy.get(cesc('#\\/p_3c') + ' > span:nth-of-type(5) input').should('have.value', 'v'); - // cy.get(cesc('#\\/p_3d') + ' > span:nth-of-type(5) input').should('have.value', 'v'); - // cy.get(cesc('#\\/p_3e') + ' > span:nth-of-type(5) input').should('have.value', 'v'); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}0{enter}", { - force: true, - }); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - - cy.get(cesc("#\\/p_1") + " > span:nth-of-type(3) .mjx-mrow").should( - "not.exist", - ); - cy.get(cesc("#\\/p_1a") + " > span:nth-of-type(3) .mjx-mrow").should( - "not.exist", - ); - cy.get( - cesc("#\\/p_1b") + " > span > span:nth-of-type(3) .mjx-mrow", - ).should("not.exist"); - cy.get(cesc("#\\/p_1c") + " > span:nth-of-type(3) .mjx-mrow").should( - "not.exist", - ); - cy.get( - cesc("#\\/p_1d") + " > span > span:nth-of-type(3) .mjx-mrow", - ).should("not.exist"); - cy.get( - cesc("#\\/p_1e") + " > span > span:nth-of-type(3) .mjx-mrow", - ).should("not.exist"); - - cy.get(cesc("#\\/p_2") + " > span:nth-of-type(3) .mjx-mrow").should( - "not.exist", - ); - cy.get(cesc("#\\/p_2a") + " > span:nth-of-type(3) .mjx-mrow").should( - "not.exist", - ); - cy.get( - cesc("#\\/p_2b") + " > span > span:nth-of-type(3) .mjx-mrow", - ).should("not.exist"); - cy.get(cesc("#\\/p_2c") + " > span:nth-of-type(3) .mjx-mrow").should( - "not.exist", - ); - cy.get( - cesc("#\\/p_2d") + " > span > span:nth-of-type(3) .mjx-mrow", - ).should("not.exist"); - cy.get( - cesc("#\\/p_2e") + " > span > span:nth-of-type(3) .mjx-mrow", - ).should("not.exist"); - - cy.get(cesc("#\\/p_1") + " > span:nth-of-type(1) .mjx-mrow").should( - "contain.text", - "x", - ); - - // cy.get(cesc('#\\/p_original') + ' > span:nth-of-type(1) input').should('have.value', 'x'); - - cy.get(cesc("#\\/p_1") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_1a") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_1b") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_1c") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_1d") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_1e") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - - cy.get(cesc("#\\/p_2") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_2a") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_2b") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_2c") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_2d") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/p_2e") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - - // cy.get(cesc('#\\/p_3') + ' > span:nth-of-type(1) input').should('have.value', 'x'); - // cy.get(cesc('#\\/p_3a') + ' > span:nth-of-type(1) input').should('have.value', 'x'); - // cy.get(cesc('#\\/p_3b') + ' > span:nth-of-type(1) input').should('have.value', 'x'); - // cy.get(cesc('#\\/p_3c') + ' > span:nth-of-type(1) input').should('have.value', 'x'); - // cy.get(cesc('#\\/p_3d') + ' > span:nth-of-type(1) input').should('have.value', 'x'); - // cy.get(cesc('#\\/p_3e') + ' > span:nth-of-type(1) input').should('have.value', 'x'); - - // cy.get(cesc('#\\/p_original') + ' > span:nth-of-type(2) input').should('have.value', 'y'); - - cy.get(cesc("#\\/p_1") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/p_1a") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/p_1b") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/p_1c") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/p_1d") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/p_1e") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - - cy.get(cesc("#\\/p_2") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/p_2a") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/p_2b") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/p_2c") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/p_2d") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/p_2e") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - - // cy.get(cesc('#\\/p_3') + ' > span:nth-of-type(2) input').should('have.value', 'y'); - // cy.get(cesc('#\\/p_3a') + ' > span:nth-of-type(2) input').should('have.value', 'y'); - // cy.get(cesc('#\\/p_3b') + ' > span:nth-of-type(2) input').should('have.value', 'y'); - // cy.get(cesc('#\\/p_3c') + ' > span:nth-of-type(2) input').should('have.value', 'y'); - // cy.get(cesc('#\\/p_3d') + ' > span:nth-of-type(2) input').should('have.value', 'y'); - // cy.get(cesc('#\\/p_3e') + ' > span:nth-of-type(2) input').should('have.value', 'y'); - - cy.get(cesc("#\\/p_3") + " > span:nth-of-type(1) textarea").type( - "{end}{backspace}a{enter}", - { force: true }, - ); - cy.get(cesc("#\\/p_3a") + " > span:nth-of-type(2) textarea").type( - "{end}{backspace}b{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/p_1") + " > span:nth-of-type(2) .mjx-mrow").should( - "contain.text", - "b", - ); - - // cy.get(cesc('#\\/p_original') + ' > span:nth-of-type(1) input').should('have.value', 'a'); - - cy.get(cesc("#\\/p_1") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_1a") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_1b") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_1c") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_1d") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_1e") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - - cy.get(cesc("#\\/p_2") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_2a") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_2b") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_2c") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_2d") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_2e") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - - // cy.get(cesc('#\\/p_3') + ' > span:nth-of-type(1) input').should('have.value', 'a'); - // cy.get(cesc('#\\/p_3a') + ' > span:nth-of-type(1) input').should('have.value', 'a'); - // cy.get(cesc('#\\/p_3b') + ' > span:nth-of-type(1) input').should('have.value', 'a'); - // cy.get(cesc('#\\/p_3c') + ' > span:nth-of-type(1) input').should('have.value', 'a'); - // cy.get(cesc('#\\/p_3d') + ' > span:nth-of-type(1) input').should('have.value', 'a'); - // cy.get(cesc('#\\/p_3e') + ' > span:nth-of-type(1) input').should('have.value', 'a'); - - // cy.get(cesc('#\\/p_original') + ' > span:nth-of-type(2) input').should('have.value', 'b'); - - cy.get(cesc("#\\/p_1") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_1a") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_1b") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_1c") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_1d") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_1e") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - - cy.get(cesc("#\\/p_2") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_2a") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_2b") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_2c") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_2d") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_2e") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - - // cy.get(cesc('#\\/p_3') + ' > span:nth-of-type(2) input').should('have.value', 'b'); - // cy.get(cesc('#\\/p_3a') + ' > span:nth-of-type(2) input').should('have.value', 'b'); - // cy.get(cesc('#\\/p_3b') + ' > span:nth-of-type(2) input').should('have.value', 'b'); - // cy.get(cesc('#\\/p_3c') + ' > span:nth-of-type(2) input').should('have.value', 'b'); - // cy.get(cesc('#\\/p_3d') + ' > span:nth-of-type(2) input').should('have.value', 'b'); - // cy.get(cesc('#\\/p_3e') + ' > span:nth-of-type(2) input').should('have.value', 'b'); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}5{enter}", { - force: true, - }); - - cy.get(cesc("#\\/p_1") + " > span:nth-of-type(5) .mjx-mrow").should( - "contain.text", - "v", - ); - - // cy.get(cesc('#\\/p_original') + ' > span:nth-of-type(1) input').should('have.value', 'a'); - - cy.get(cesc("#\\/p_1") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_1a") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_1b") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_1c") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_1d") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_1e") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - - cy.get(cesc("#\\/p_2") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_2a") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_2b") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_2c") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_2d") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_2e") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - - // cy.get(cesc('#\\/p_3') + ' > span:nth-of-type(1) input').should('have.value', 'a'); - // cy.get(cesc('#\\/p_3a') + ' > span:nth-of-type(1) input').should('have.value', 'a'); - // cy.get(cesc('#\\/p_3b') + ' > span:nth-of-type(1) input').should('have.value', 'a'); - // cy.get(cesc('#\\/p_3c') + ' > span:nth-of-type(1) input').should('have.value', 'a'); - // cy.get(cesc('#\\/p_3d') + ' > span:nth-of-type(1) input').should('have.value', 'a'); - // cy.get(cesc('#\\/p_3e') + ' > span:nth-of-type(1) input').should('have.value', 'a'); - - // cy.get(cesc('#\\/p_original') + ' > span:nth-of-type(2) input').should('have.value', 'b'); - - cy.get(cesc("#\\/p_1") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_1a") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_1b") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_1c") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_1d") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_1e") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - - cy.get(cesc("#\\/p_2") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_2a") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_2b") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_2c") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_2d") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_2e") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - - // cy.get(cesc('#\\/p_3') + ' > span:nth-of-type(2) input').should('have.value', 'b'); - // cy.get(cesc('#\\/p_3a') + ' > span:nth-of-type(2) input').should('have.value', 'b'); - // cy.get(cesc('#\\/p_3b') + ' > span:nth-of-type(2) input').should('have.value', 'b'); - // cy.get(cesc('#\\/p_3c') + ' > span:nth-of-type(2) input').should('have.value', 'b'); - // cy.get(cesc('#\\/p_3d') + ' > span:nth-of-type(2) input').should('have.value', 'b'); - // cy.get(cesc('#\\/p_3e') + ' > span:nth-of-type(2) input').should('have.value', 'b'); - - // cy.get(cesc('#\\/p_original') + ' > span:nth-of-type(3) input').should('have.value', 'z'); - - cy.get(cesc("#\\/p_1") + " > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/p_1a") + " > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/p_1b") + " > span > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/p_1c") + " > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/p_1d") + " > span > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/p_1e") + " > span > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - - cy.get(cesc("#\\/p_2") + " > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/p_2a") + " > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/p_2b") + " > span > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/p_2c") + " > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/p_2d") + " > span > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/p_2e") + " > span > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - - // cy.get(cesc('#\\/p_3') + ' > span:nth-of-type(3) input').should('have.value', 'z'); - // cy.get(cesc('#\\/p_3a') + ' > span:nth-of-type(3) input').should('have.value', 'z'); - // cy.get(cesc('#\\/p_3b') + ' > span:nth-of-type(3) input').should('have.value', 'z'); - // cy.get(cesc('#\\/p_3c') + ' > span:nth-of-type(3) input').should('have.value', 'z'); - // cy.get(cesc('#\\/p_3d') + ' > span:nth-of-type(3) input').should('have.value', 'z'); - // cy.get(cesc('#\\/p_3e') + ' > span:nth-of-type(3) input').should('have.value', 'z'); - - // cy.get(cesc('#\\/p_original') + ' > span:nth-of-type(4) input').should('have.value', 'u'); - - cy.get(cesc("#\\/p_1") + " > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("u"); - }); - cy.get(cesc("#\\/p_1a") + " > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("u"); - }); - cy.get(cesc("#\\/p_1b") + " > span > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("u"); - }); - cy.get(cesc("#\\/p_1c") + " > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("u"); - }); - cy.get(cesc("#\\/p_1d") + " > span > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("u"); - }); - cy.get(cesc("#\\/p_1e") + " > span > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("u"); - }); - - cy.get(cesc("#\\/p_2") + " > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("u"); - }); - cy.get(cesc("#\\/p_2a") + " > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("u"); - }); - cy.get(cesc("#\\/p_2b") + " > span > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("u"); - }); - cy.get(cesc("#\\/p_2c") + " > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("u"); - }); - cy.get(cesc("#\\/p_2d") + " > span > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("u"); - }); - cy.get(cesc("#\\/p_2e") + " > span > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("u"); - }); - - // cy.get(cesc('#\\/p_3') + ' > span:nth-of-type(4) input').should('have.value', 'u'); - // cy.get(cesc('#\\/p_3a') + ' > span:nth-of-type(4) input').should('have.value', 'u'); - // cy.get(cesc('#\\/p_3b') + ' > span:nth-of-type(4) input').should('have.value', 'u'); - // cy.get(cesc('#\\/p_3c') + ' > span:nth-of-type(4) input').should('have.value', 'u'); - // cy.get(cesc('#\\/p_3d') + ' > span:nth-of-type(4) input').should('have.value', 'u'); - // cy.get(cesc('#\\/p_3e') + ' > span:nth-of-type(4) input').should('have.value', 'u'); - - // cy.get(cesc('#\\/p_original') + ' > span:nth-of-type(5) input').should('have.value', 'v'); - - cy.get(cesc("#\\/p_1") + " > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v"); - }); - cy.get(cesc("#\\/p_1a") + " > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v"); - }); - cy.get(cesc("#\\/p_1b") + " > span > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v"); - }); - cy.get(cesc("#\\/p_1c") + " > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v"); - }); - cy.get(cesc("#\\/p_1d") + " > span > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v"); - }); - cy.get(cesc("#\\/p_1e") + " > span > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v"); - }); - - cy.get(cesc("#\\/p_2") + " > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v"); - }); - cy.get(cesc("#\\/p_2a") + " > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v"); - }); - cy.get(cesc("#\\/p_2b") + " > span > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v"); - }); - cy.get(cesc("#\\/p_2c") + " > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v"); - }); - cy.get(cesc("#\\/p_2d") + " > span > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v"); - }); - cy.get(cesc("#\\/p_2e") + " > span > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("v"); - }); - - // cy.get(cesc('#\\/p_3') + ' > span:nth-of-type(5) input').should('have.value', 'v'); - // cy.get(cesc('#\\/p_3a') + ' > span:nth-of-type(5) input').should('have.value', 'v'); - // cy.get(cesc('#\\/p_3b') + ' > span:nth-of-type(5) input').should('have.value', 'v'); - // cy.get(cesc('#\\/p_3c') + ' > span:nth-of-type(5) input').should('have.value', 'v'); - // cy.get(cesc('#\\/p_3d') + ' > span:nth-of-type(5) input').should('have.value', 'v'); - // cy.get(cesc('#\\/p_3e') + ' > span:nth-of-type(5) input').should('have.value', 'v'); - - cy.get( - cesc("#\\/p_3b") + " > span > span:nth-of-type(3) textarea", - ).type("{end}{backspace}c{enter}", { force: true }); - cy.get(cesc("#\\/p_3c") + " > span:nth-of-type(4) textarea").type( - "{end}{backspace}d{enter}", - { force: true }, - ); - cy.get( - cesc("#\\/p_3d") + " > span > span:nth-of-type(5) textarea", - ).type("{end}{backspace}e{enter}", { force: true }); - - cy.get(cesc("#\\/p_1") + " > span:nth-of-type(5) .mjx-mrow").should( - "contain.text", - "e", - ); - - // cy.get(cesc('#\\/p_original') + ' > span:nth-of-type(1) input').should('have.value', 'a'); - - cy.get(cesc("#\\/p_1") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_1a") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_1b") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_1c") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_1d") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_1e") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - - cy.get(cesc("#\\/p_2") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_2a") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_2b") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_2c") + " > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_2d") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p_2e") + " > span > span:nth-of-type(1)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - - // cy.get(cesc('#\\/p_3') + ' > span:nth-of-type(1) input').should('have.value', 'a'); - // cy.get(cesc('#\\/p_3a') + ' > span:nth-of-type(1) input').should('have.value', 'a'); - // cy.get(cesc('#\\/p_3b') + ' > span:nth-of-type(1) input').should('have.value', 'a'); - // cy.get(cesc('#\\/p_3c') + ' > span:nth-of-type(1) input').should('have.value', 'a'); - // cy.get(cesc('#\\/p_3d') + ' > span:nth-of-type(1) input').should('have.value', 'a'); - // cy.get(cesc('#\\/p_3e') + ' > span:nth-of-type(1) input').should('have.value', 'a'); - - // cy.get(cesc('#\\/p_original') + ' > span:nth-of-type(2) input').should('have.value', 'b'); - - cy.get(cesc("#\\/p_1") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_1a") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_1b") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_1c") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_1d") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_1e") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - - cy.get(cesc("#\\/p_2") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_2a") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_2b") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_2c") + " > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_2d") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - cy.get(cesc("#\\/p_2e") + " > span > span:nth-of-type(2)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("b"); - }); - - // cy.get(cesc('#\\/p_3') + ' > span:nth-of-type(2) input').should('have.value', 'b'); - // cy.get(cesc('#\\/p_3a') + ' > span:nth-of-type(2) input').should('have.value', 'b'); - // cy.get(cesc('#\\/p_3b') + ' > span:nth-of-type(2) input').should('have.value', 'b'); - // cy.get(cesc('#\\/p_3c') + ' > span:nth-of-type(2) input').should('have.value', 'b'); - // cy.get(cesc('#\\/p_3d') + ' > span:nth-of-type(2) input').should('have.value', 'b'); - // cy.get(cesc('#\\/p_3e') + ' > span:nth-of-type(2) input').should('have.value', 'b'); - - // cy.get(cesc('#\\/p_original') + ' > span:nth-of-type(3) input').should('have.value', 'c'); - - cy.get(cesc("#\\/p_1") + " > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("c"); - }); - cy.get(cesc("#\\/p_1a") + " > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("c"); - }); - cy.get(cesc("#\\/p_1b") + " > span > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("c"); - }); - cy.get(cesc("#\\/p_1c") + " > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("c"); - }); - cy.get(cesc("#\\/p_1d") + " > span > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("c"); - }); - cy.get(cesc("#\\/p_1e") + " > span > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("c"); - }); - - cy.get(cesc("#\\/p_2") + " > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("c"); - }); - cy.get(cesc("#\\/p_2a") + " > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("c"); - }); - cy.get(cesc("#\\/p_2b") + " > span > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("c"); - }); - cy.get(cesc("#\\/p_2c") + " > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("c"); - }); - cy.get(cesc("#\\/p_2d") + " > span > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("c"); - }); - cy.get(cesc("#\\/p_2e") + " > span > span:nth-of-type(3)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("c"); - }); - - // cy.get(cesc('#\\/p_3') + ' > span:nth-of-type(3) input').should('have.value', 'c'); - // cy.get(cesc('#\\/p_3a') + ' > span:nth-of-type(3) input').should('have.value', 'c'); - // cy.get(cesc('#\\/p_3b') + ' > span:nth-of-type(3) input').should('have.value', 'c'); - // cy.get(cesc('#\\/p_3c') + ' > span:nth-of-type(3) input').should('have.value', 'c'); - // cy.get(cesc('#\\/p_3d') + ' > span:nth-of-type(3) input').should('have.value', 'c'); - // cy.get(cesc('#\\/p_3e') + ' > span:nth-of-type(3) input').should('have.value', 'c'); - - // cy.get(cesc('#\\/p_original') + ' > span:nth-of-type(4) input').should('have.value', 'd'); - - cy.get(cesc("#\\/p_1") + " > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("d"); - }); - cy.get(cesc("#\\/p_1a") + " > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("d"); - }); - cy.get(cesc("#\\/p_1b") + " > span > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("d"); - }); - cy.get(cesc("#\\/p_1c") + " > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("d"); - }); - cy.get(cesc("#\\/p_1d") + " > span > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("d"); - }); - cy.get(cesc("#\\/p_1e") + " > span > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("d"); - }); - - cy.get(cesc("#\\/p_2") + " > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("d"); - }); - cy.get(cesc("#\\/p_2a") + " > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("d"); - }); - cy.get(cesc("#\\/p_2b") + " > span > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("d"); - }); - cy.get(cesc("#\\/p_2c") + " > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("d"); - }); - cy.get(cesc("#\\/p_2d") + " > span > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("d"); - }); - cy.get(cesc("#\\/p_2e") + " > span > span:nth-of-type(4)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("d"); - }); - - // cy.get(cesc('#\\/p_3') + ' > span:nth-of-type(4) input').should('have.value', 'd'); - // cy.get(cesc('#\\/p_3a') + ' > span:nth-of-type(4) input').should('have.value', 'd'); - // cy.get(cesc('#\\/p_3b') + ' > span:nth-of-type(4) input').should('have.value', 'd'); - // cy.get(cesc('#\\/p_3c') + ' > span:nth-of-type(4) input').should('have.value', 'd'); - // cy.get(cesc('#\\/p_3d') + ' > span:nth-of-type(4) input').should('have.value', 'd'); - // cy.get(cesc('#\\/p_3e') + ' > span:nth-of-type(4) input').should('have.value', 'd'); - - // cy.get(cesc('#\\/p_original') + ' > span:nth-of-type(5) input').should('have.value', 'e'); - - cy.get(cesc("#\\/p_1") + " > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("e"); - }); - cy.get(cesc("#\\/p_1a") + " > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("e"); - }); - cy.get(cesc("#\\/p_1b") + " > span > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("e"); - }); - cy.get(cesc("#\\/p_1c") + " > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("e"); - }); - cy.get(cesc("#\\/p_1d") + " > span > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("e"); - }); - cy.get(cesc("#\\/p_1e") + " > span > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("e"); - }); - - cy.get(cesc("#\\/p_2") + " > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("e"); - }); - cy.get(cesc("#\\/p_2a") + " > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("e"); - }); - cy.get(cesc("#\\/p_2b") + " > span > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("e"); - }); - cy.get(cesc("#\\/p_2c") + " > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("e"); - }); - cy.get(cesc("#\\/p_2d") + " > span > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("e"); - }); - cy.get(cesc("#\\/p_2e") + " > span > span:nth-of-type(5)") - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("e"); - }); - - // cy.get(cesc('#\\/p_3') + ' > span:nth-of-type(5) input').should('have.value', 'e'); - // cy.get(cesc('#\\/p_3a') + ' > span:nth-of-type(5) input').should('have.value', 'e'); - // cy.get(cesc('#\\/p_3b') + ' > span:nth-of-type(5) input').should('have.value', 'e'); - // cy.get(cesc('#\\/p_3c') + ' > span:nth-of-type(5) input').should('have.value', 'e'); - // cy.get(cesc('#\\/p_3d') + ' > span:nth-of-type(5) input').should('have.value', 'e'); - // cy.get(cesc('#\\/p_3e') + ' > span:nth-of-type(5) input').should('have.value', 'e'); - }); - - // main point: no longer turn inputs into their value - // even with copy a collection with a macro - it("test macros by collecting inputs and others", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - 2$a - $b there - not $c - - -

-

$_collect1

-

$_group1

-

$_collect1

-

$_group1

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let group1Replacements = stateVariables[ - "/_document1" - ].activeChildren.slice(2, 15); - let collect1Replacements = - stateVariables["/pcollect1"].activeChildren; - let collect2Replacements = - stateVariables["/pcollect2"].activeChildren; - let group2Replacements = stateVariables["/pgroup2"].activeChildren; - let collect3Replacements = - stateVariables["/pcollect3"].activeChildren; - let group3Replacements = stateVariables["/pgroup3"].activeChildren; - - expect(group1Replacements.length).eq(13); - expect(collect1Replacements.length).eq(6); - expect(collect2Replacements.length).eq(6); - expect(group2Replacements.length).eq(13); - expect(collect3Replacements.length).eq(6); - expect(group3Replacements.length).eq(13); - - expect(group1Replacements[1].componentType).eq("mathInput"); - expect( - stateVariables[group1Replacements[1].componentName].stateValues - .value, - ).eq("x"); - expect(collect1Replacements[0].componentType).eq("mathInput"); - expect( - stateVariables[collect1Replacements[0].componentName] - .stateValues.value, - ).eq("x"); - expect(collect2Replacements[0].componentType).eq("mathInput"); - expect( - stateVariables[collect2Replacements[0].componentName] - .stateValues.value, - ).eq("x"); - expect(group2Replacements[1].componentType).eq("mathInput"); - expect( - stateVariables[group2Replacements[1].componentName].stateValues - .value, - ).eq("x"); - expect(collect3Replacements[0].componentType).eq("mathInput"); - expect( - stateVariables[collect3Replacements[0].componentName] - .stateValues.value, - ).eq("x"); - expect(group3Replacements[1].componentType).eq("mathInput"); - expect( - stateVariables[group3Replacements[1].componentName].stateValues - .value, - ).eq("x"); - - expect(group1Replacements[3].componentType).eq("textInput"); - expect( - stateVariables[group1Replacements[3].componentName].stateValues - .value, - ).eq("hello"); - expect(collect1Replacements[1].componentType).eq("textInput"); - expect( - stateVariables[collect1Replacements[1].componentName] - .stateValues.value, - ).eq("hello"); - expect(collect2Replacements[1].componentType).eq("textInput"); - expect( - stateVariables[collect2Replacements[1].componentName] - .stateValues.value, - ).eq("hello"); - expect(group2Replacements[3].componentType).eq("textInput"); - expect( - stateVariables[group2Replacements[3].componentName].stateValues - .value, - ).eq("hello"); - expect(collect3Replacements[1].componentType).eq("textInput"); - expect( - stateVariables[collect3Replacements[1].componentName] - .stateValues.value, - ).eq("hello"); - expect(group3Replacements[3].componentType).eq("textInput"); - expect( - stateVariables[group3Replacements[3].componentName].stateValues - .value, - ).eq("hello"); - - expect(group1Replacements[5].componentType).eq("booleanInput"); - expect( - stateVariables[group1Replacements[5].componentName].stateValues - .value, - ).eq(false); - expect(collect1Replacements[2].componentType).eq("booleanInput"); - expect( - stateVariables[collect1Replacements[2].componentName] - .stateValues.value, - ).eq(false); - expect(collect2Replacements[2].componentType).eq("booleanInput"); - expect( - stateVariables[collect2Replacements[2].componentName] - .stateValues.value, - ).eq(false); - expect(group2Replacements[5].componentType).eq("booleanInput"); - expect( - stateVariables[group2Replacements[5].componentName].stateValues - .value, - ).eq(false); - expect(collect3Replacements[2].componentType).eq("booleanInput"); - expect( - stateVariables[collect3Replacements[2].componentName] - .stateValues.value, - ).eq(false); - expect(group3Replacements[5].componentType).eq("booleanInput"); - expect( - stateVariables[group3Replacements[5].componentName].stateValues - .value, - ).eq(false); - - expect(group1Replacements[7].componentType).eq("math"); - expect( - stateVariables[group1Replacements[7].componentName].stateValues - .value, - ).eqls(["*", 2, "x"]); - expect(collect1Replacements[3].componentType).eq("math"); - expect( - stateVariables[collect1Replacements[3].componentName] - .stateValues.value, - ).eqls(["*", 2, "x"]); - expect(collect2Replacements[3].componentType).eq("math"); - expect( - stateVariables[collect2Replacements[3].componentName] - .stateValues.value, - ).eqls(["*", 2, "x"]); - expect(group2Replacements[7].componentType).eq("math"); - expect( - stateVariables[group2Replacements[7].componentName].stateValues - .value, - ).eqls(["*", 2, "x"]); - expect(collect3Replacements[3].componentType).eq("math"); - expect( - stateVariables[collect3Replacements[3].componentName] - .stateValues.value, - ).eqls(["*", 2, "x"]); - expect(group3Replacements[7].componentType).eq("math"); - expect( - stateVariables[group3Replacements[7].componentName].stateValues - .value, - ).eqls(["*", 2, "x"]); - - expect(group1Replacements[9].componentType).eq("text"); - expect( - stateVariables[group1Replacements[9].componentName].stateValues - .value, - ).eq("hello there"); - expect(collect1Replacements[4].componentType).eq("text"); - expect( - stateVariables[collect1Replacements[4].componentName] - .stateValues.value, - ).eq("hello there"); - expect(collect2Replacements[4].componentType).eq("text"); - expect( - stateVariables[collect2Replacements[4].componentName] - .stateValues.value, - ).eq("hello there"); - expect(group2Replacements[9].componentType).eq("text"); - expect( - stateVariables[group2Replacements[9].componentName].stateValues - .value, - ).eq("hello there"); - expect(collect3Replacements[4].componentType).eq("text"); - expect( - stateVariables[collect3Replacements[4].componentName] - .stateValues.value, - ).eq("hello there"); - expect(group3Replacements[9].componentType).eq("text"); - expect( - stateVariables[group3Replacements[9].componentName].stateValues - .value, - ).eq("hello there"); - - expect(group1Replacements[11].componentType).eq("boolean"); - expect( - stateVariables[group1Replacements[11].componentName].stateValues - .value, - ).eq(true); - expect(collect1Replacements[5].componentType).eq("boolean"); - expect( - stateVariables[collect1Replacements[5].componentName] - .stateValues.value, - ).eq(true); - expect(collect2Replacements[5].componentType).eq("boolean"); - expect( - stateVariables[collect2Replacements[5].componentName] - .stateValues.value, - ).eq(true); - expect(group2Replacements[11].componentType).eq("boolean"); - expect( - stateVariables[group2Replacements[11].componentName].stateValues - .value, - ).eq(true); - expect(collect3Replacements[5].componentType).eq("boolean"); - expect( - stateVariables[collect3Replacements[5].componentName] - .stateValues.value, - ).eq(true); - expect(group3Replacements[11].componentType).eq("boolean"); - expect( - stateVariables[group3Replacements[11].componentName].stateValues - .value, - ).eq(true); - }); - }); - - it("collect does not ignore hide", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -
- secret - public -
-

Hidden by default:

-

Force to reveal:

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - cy.get(cesc("#\\/_section1")).should("contain.text", "public"); - cy.get(cesc("#\\/_section1")).should("not.contain.text", "secret"); - - cy.get(cesc("#\\/_p1")).should( - "have.text", - "Hidden by default: public", - ); - cy.get(cesc("#\\/_p2")).should( - "have.text", - "Force to reveal: secret, public", - ); - }); - - it("collect keeps hidden children hidden", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -
-

Hidden text: secret

- $theP1{name="theP2"} -

Hidden paragraph with hidden text: top secret

- $theP3{name="theP4"} -
- - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - cy.get(cesc("#\\/theP1")).should("have.text", "Hidden text: "); - cy.get(cesc("#\\/theP2")).should("have.text", "Hidden text: "); - cy.get(cesc("#\\/theP3")).should("not.exist"); - cy.get(cesc("#\\/theP4")).should("not.exist"); - cy.get(cesc("#\\/cp1")).should("have.text", "Hidden text: "); - cy.get(cesc("#\\/cp2")).should("have.text", "Hidden text: "); - cy.get(cesc("#\\/cp3")).should("not.exist"); - cy.get(cesc("#\\/cp4")).should("not.exist"); - cy.get(cesc("#\\/cp5")).should("have.text", "Hidden text: "); - cy.get(cesc("#\\/cp6")).should("have.text", "Hidden text: "); - cy.get(cesc("#\\/cp7")).should( - "have.text", - "Hidden paragraph with hidden text: ", - ); - cy.get(cesc("#\\/cp8")).should( - "have.text", - "Hidden paragraph with hidden text: ", - ); - }); - - it("collecting from within a hidden section", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -
-

Hidden text: secret

- $theP1{name="theP2"} -

Hidden paragraph with hidden text: top secret

- $theP3{name="theP4"} -
- - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - cy.get(cesc("#\\/theP1")).should("not.exist"); - cy.get(cesc("#\\/theP2")).should("not.exist"); - cy.get(cesc("#\\/theP3")).should("not.exist"); - cy.get(cesc("#\\/theP4")).should("not.exist"); - cy.get(cesc("#\\/cp1")).should("have.text", "Hidden text: "); - cy.get(cesc("#\\/cp2")).should("have.text", "Hidden text: "); - cy.get(cesc("#\\/cp3")).should("not.exist"); - cy.get(cesc("#\\/cp4")).should("not.exist"); - cy.get(cesc("#\\/cp5")).should("have.text", "Hidden text: "); - cy.get(cesc("#\\/cp6")).should("have.text", "Hidden text: "); - cy.get(cesc("#\\/cp7")).should( - "have.text", - "Hidden paragraph with hidden text: ", - ); - cy.get(cesc("#\\/cp8")).should( - "have.text", - "Hidden paragraph with hidden text: ", - ); - }); - - it("copies hide dynamically", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

- - - - -

- - - - - - - -

Number of points

- -

collect 1:

-

collect 2:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/c1")).should( - "have.text", - "collect 1: Hello, a! Hello, b! Hello, c! Hello, d! ", - ); - cy.get(cesc("#\\/c2")).should("have.text", "collect 2: "); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}6{enter}", { - force: true, - }); - - cy.get(cesc("#\\/c1")).should( - "have.text", - "collect 1: Hello, a! Hello, b! Hello, c! Hello, d! Hello, e! Hello, f! ", - ); - cy.get(cesc("#\\/c2")).should("have.text", "collect 2: "); - - cy.get(cesc("#\\/h1")).click(); - cy.get(cesc("#\\/h2")).click(); - - cy.get(cesc("#\\/c1")).should("have.text", "collect 1: "); - cy.get(cesc("#\\/c2")).should( - "have.text", - "collect 2: Hello, a! Hello, b! Hello, c! Hello, d! Hello, e! Hello, f! ", - ); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}8{enter}", { - force: true, - }); - - cy.get(cesc("#\\/c1")).should("have.text", "collect 1: "); - cy.get(cesc("#\\/c2")).should( - "have.text", - "collect 2: Hello, a! Hello, b! Hello, c! Hello, d! Hello, e! Hello, f! Hello, g! Hello, h! ", - ); - - cy.get(cesc("#\\/h1")).click(); - cy.get(cesc("#\\/h2")).click(); - - cy.get(cesc("#\\/c1")).should( - "have.text", - "collect 1: Hello, a! Hello, b! Hello, c! Hello, d! Hello, e! Hello, f! Hello, g! Hello, h! ", - ); - cy.get(cesc("#\\/c2")).should("have.text", "collect 2: "); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - - cy.get(cesc("#\\/c1")).should( - "have.text", - "collect 1: Hello, a! Hello, b! Hello, c! ", - ); - cy.get(cesc("#\\/c2")).should("have.text", "collect 2: "); - - cy.get(cesc("#\\/h1")).click(); - cy.get(cesc("#\\/h2")).click(); - - cy.get(cesc("#\\/c1")).should("have.text", "collect 1: "); - cy.get(cesc("#\\/c2")).should( - "have.text", - "collect 2: Hello, a! Hello, b! Hello, c! ", - ); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}4{enter}", { - force: true, - }); - - cy.get(cesc("#\\/c1")).should("have.text", "collect 1: "); - cy.get(cesc("#\\/c2")).should( - "have.text", - "collect 2: Hello, a! Hello, b! Hello, c! Hello, d! ", - ); - }); - - it("asList", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

We an apple, a banana, and a cherry.

- -

-

- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/pdefault")).should( - "have.text", - "apple, banana, cherry", - ); - cy.get(cesc2("#/pnolist")).should("have.text", "applebananacherry"); - }); - - it("collect warnings", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let errorWarnings = await win.returnErrorWarnings1(); - - expect(errorWarnings.errors.length).eq(0); - expect(errorWarnings.warnings.length).eq(2); - - expect(errorWarnings.warnings[0].message).contain( - "Cannot collect components of type as it is an invalid component type", - ); - expect(errorWarnings.warnings[0].level).eq(1); - expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(6); - expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(5); - expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(6); - expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(47); - - expect(errorWarnings.warnings[1].message).contain( - "No source found for collect", - ); - expect(errorWarnings.warnings[1].level).eq(1); - expect(errorWarnings.warnings[1].doenetMLrange.lineBegin).eq(5); - expect(errorWarnings.warnings[1].doenetMLrange.charBegin).eq(5); - expect(errorWarnings.warnings[1].doenetMLrange.lineEnd).eq(5); - expect(errorWarnings.warnings[1].doenetMLrange.charEnd).eq(32); - }); - }); - - // Not sure how to test with with core a web worker - it.skip("allChildrenOrdered consistent with dynamic collect and adapters", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

- begin - (1,2) - - - - - (3,4) - end -

- -

Hello there

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - function checkAllChildren(stateVariables) { - let p1AllChildren = []; - p1AllChildren.push("/A"); - p1AllChildren.push(stateVariables["/A"].adapterUsed.componentName); - p1AllChildren.push("/_map1"); - - let map = stateVariables["/_map1"]; - - let nActiveReps = map.replacements.length; - if (map.replacementsToWithhold) { - nActiveReps -= stateVariables["/_map1"].replacementsToWithhold; - } - for (let template of map.replacements.slice(0, nActiveReps)) { - p1AllChildren.push(template.componentName); - let point = template.replacements[0]; - p1AllChildren.push(point.componentName); - p1AllChildren.push(point.adapterUsed.componentName); - } - p1AllChildren.push("/B"); - p1AllChildren.push(stateVariables["/B"].adapterUsed.componentName); - - expect(stateVariables["/_p1"].allChildrenOrdered).eqls( - p1AllChildren, - ); - - let p2AllChildren = []; - p2AllChildren.push("/_collect1"); - let collect = stateVariables["/_collect1"]; - nActiveReps = collect.replacements.length; - if (collect.replacementsToWithhold) { - nActiveReps -= - stateVariables["/_collect1"].replacementsToWithhold; - } - for (let rep of collect.replacements.slice(0, nActiveReps)) { - p2AllChildren.push(rep.componentName); - p2AllChildren.push(rep.adapterUsed.componentName); - } - - expect(stateVariables["/_p2"].allChildrenOrdered).eqls( - p2AllChildren, - ); - } - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - checkAllChildren(stateVariables); - }); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}4{enter}", { - force: true, - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - checkAllChildren(stateVariables); - }); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}0{enter}", { - force: true, - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - checkAllChildren(stateVariables); - }); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - checkAllChildren(stateVariables); - }); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}1{enter}", { - force: true, - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - checkAllChildren(stateVariables); - }); - }); - - it("overwrite attributes using collect", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

Collected points are fixed:

- - - (1,2) - (3,4) - - - - - - - - - - - - - $A2.fixed{assignNames="A2fixed"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.fixed).eq(false); - expect(stateVariables["/B"].stateValues.fixed).eq(false); - expect(stateVariables["/A2"].stateValues.fixed).eq(false); - expect(stateVariables["/B2"].stateValues.fixed).eq(false); - expect(stateVariables["/g3/A2"].stateValues.fixed).eq(false); - expect(stateVariables["/g3/B2"].stateValues.fixed).eq(false); - expect(stateVariables["/Ax"].stateValues.fixed).eq(false); - expect(stateVariables["/Bx"].stateValues.fixed).eq(false); - expect(stateVariables["/al2/Ax"].stateValues.fixed).eq(false); - expect(stateVariables["/al2/Bx"].stateValues.fixed).eq(false); - }); - - cy.get(cesc("#\\/fixed")).click(); - - cy.get(cesc("#\\/A2fixed")).should("have.text", "true"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.fixed).eq(false); - expect(stateVariables["/B"].stateValues.fixed).eq(false); - expect(stateVariables["/A2"].stateValues.fixed).eq(true); - expect(stateVariables["/B2"].stateValues.fixed).eq(true); - expect(stateVariables["/g3/A2"].stateValues.fixed).eq(true); - expect(stateVariables["/g3/B2"].stateValues.fixed).eq(true); - expect(stateVariables["/Ax"].stateValues.fixed).eq(true); - expect(stateVariables["/Bx"].stateValues.fixed).eq(true); - expect(stateVariables["/al2/Ax"].stateValues.fixed).eq(true); - expect(stateVariables["/al2/Bx"].stateValues.fixed).eq(true); - }); - - cy.get(cesc("#\\/fixed")).click(); - - cy.get(cesc("#\\/A2fixed")).should("have.text", "false"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.fixed).eq(false); - expect(stateVariables["/B"].stateValues.fixed).eq(false); - expect(stateVariables["/A2"].stateValues.fixed).eq(false); - expect(stateVariables["/B2"].stateValues.fixed).eq(false); - expect(stateVariables["/g3/A2"].stateValues.fixed).eq(false); - expect(stateVariables["/g3/B2"].stateValues.fixed).eq(false); - expect(stateVariables["/Ax"].stateValues.fixed).eq(false); - expect(stateVariables["/Bx"].stateValues.fixed).eq(false); - expect(stateVariables["/al2/Ax"].stateValues.fixed).eq(false); - expect(stateVariables["/al2/Bx"].stateValues.fixed).eq(false); - }); - }); - - it("collect componentIndex", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

n:

- - - (1,2) - (3,4) - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let x1 = 1, - y1 = 2, - x2 = 3, - y2 = 4; - - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/Bx") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/Bx") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/A2"]).eq(undefined); - expect(stateVariables["/g3/A2"]).eq(undefined); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/B2"]).eq(undefined); - expect(stateVariables["/g3/B2"]).eq(undefined); - expect(stateVariables["/Ax"]).eq(undefined); - expect(stateVariables["/al2/Ax"]).eq(undefined); - expect(stateVariables["/Bx"]).eq(undefined); - expect(stateVariables["/al2/Bx"]).eq(undefined); - }); - - cy.log("restrict collection to first component"); - - cy.get(cesc("#\\/n") + " textarea").type("1{enter}", { force: true }); - - cy.get(cesc("#\\/Bx") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/Bx") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/A2"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/g3/A2"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/B2"]).eq(undefined); - expect(stateVariables["/g3/B2"]).eq(undefined); - expect(stateVariables["/Ax"].stateValues.value).eq(x1); - expect(stateVariables["/al2/Ax"].stateValues.value).eq(x1); - expect(stateVariables["/Bx"]).eq(undefined); - expect(stateVariables["/al2/Bx"]).eq(undefined); - }); - - cy.log("move copied point"); - cy.window().then(async (win) => { - (x1 = 9), (y1 = -5); - await win.callAction1({ - actionName: "movePoint", - componentName: "/A2", - args: { x: x1, y: y1 }, - }); - - cy.get(cesc("#\\/Bx") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/Bx") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/A2"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/g3/A2"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/B2"]).eq(undefined); - expect(stateVariables["/g3/B2"]).eq(undefined); - expect(stateVariables["/Ax"].stateValues.value).eq(x1); - expect(stateVariables["/al2/Ax"].stateValues.value).eq(x1); - expect(stateVariables["/Bx"]).eq(undefined); - expect(stateVariables["/al2/Bx"]).eq(undefined); - }); - }); - - cy.log("restrict collection to second component"); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/Bx") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/Bx") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/A2"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/g3/A2"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/B2"]).eq(undefined); - expect(stateVariables["/g3/B2"]).eq(undefined); - expect(stateVariables["/Ax"].stateValues.value).eq(x2); - expect(stateVariables["/al2/Ax"].stateValues.value).eq(x2); - expect(stateVariables["/Bx"]).eq(undefined); - expect(stateVariables["/al2/Bx"]).eq(undefined); - }); - }); - - cy.log("move double copied point"); - cy.window().then(async (win) => { - (x2 = 0), (y2 = 8); - await win.callAction1({ - actionName: "movePoint", - componentName: "/g3/A2", - args: { x: x2, y: y2 }, - }); - - cy.get(cesc("#\\/Bx") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/Bx") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/A2"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/g3/A2"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/B2"]).eq(undefined); - expect(stateVariables["/g3/B2"]).eq(undefined); - expect(stateVariables["/Ax"].stateValues.value).eq(x2); - expect(stateVariables["/al2/Ax"].stateValues.value).eq(x2); - expect(stateVariables["/Bx"]).eq(undefined); - expect(stateVariables["/al2/Bx"]).eq(undefined); - }); - }); - }); - - it("collect propIndex and componentIndex", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

m:

-

n:

- - - (1,2) - (3,4) - - -

- -

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let x1 = 1, - y1 = 2, - x2 = 3, - y2 = 4; - - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n4") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/n3"]).eq(undefined); - expect(stateVariables["/n4"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); - expect(stateVariables["/al2/n2"]).eq(undefined); - expect(stateVariables["/al2/n3"]).eq(undefined); - expect(stateVariables["/al2/n4"]).eq(undefined); - }); - - cy.log("set propIndex to 1"); - - cy.get(cesc("#\\/n") + " textarea").type("1{enter}", { force: true }); - - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n4") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/n3"]).eq(undefined); - expect(stateVariables["/n4"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); - expect(stateVariables["/al2/n2"]).eq(undefined); - expect(stateVariables["/al2/n3"]).eq(undefined); - expect(stateVariables["/al2/n4"]).eq(undefined); - }); - - cy.log("move point 1"); - cy.window().then(async (win) => { - (x1 = 9), (y1 = -5); - await win.callAction1({ - actionName: "movePoint", - componentName: "/A", - args: { x: x1, y: y1 }, - }); - - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n4") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/n3"]).eq(undefined); - expect(stateVariables["/n4"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); - expect(stateVariables["/al2/n2"]).eq(undefined); - expect(stateVariables["/al2/n3"]).eq(undefined); - expect(stateVariables["/al2/n4"]).eq(undefined); - }); - }); - - cy.log("set componentIndex to 2"); - - cy.get(cesc("#\\/m") + " textarea").type("2{enter}", { force: true }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n4") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(x2); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/n3"]).eq(undefined); - expect(stateVariables["/n4"]).eq(undefined); - expect(stateVariables["/al2/n1"].stateValues.value).eq(x2); - expect(stateVariables["/al2/n2"]).eq(undefined); - expect(stateVariables["/al2/n3"]).eq(undefined); - expect(stateVariables["/al2/n4"]).eq(undefined); - }); - }); - - cy.log("move point2"); - cy.window().then(async (win) => { - (x2 = 0), (y2 = 8); - await win.callAction1({ - actionName: "movePoint", - componentName: "/B", - args: { x: x2, y: y2 }, - }); - - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n4") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(x2); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/n3"]).eq(undefined); - expect(stateVariables["/n4"]).eq(undefined); - expect(stateVariables["/al2/n1"].stateValues.value).eq(x2); - expect(stateVariables["/al2/n2"]).eq(undefined); - expect(stateVariables["/al2/n3"]).eq(undefined); - expect(stateVariables["/al2/n4"]).eq(undefined); - }); - }); - - cy.log("set propIndex to 2"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y2), - ); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y2), - ); - cy.get(cesc("#\\/al2\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n4") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(y2); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/n3"]).eq(undefined); - expect(stateVariables["/n4"]).eq(undefined); - expect(stateVariables["/al2/n1"].stateValues.value).eq(y2); - expect(stateVariables["/al2/n2"]).eq(undefined); - expect(stateVariables["/al2/n3"]).eq(undefined); - expect(stateVariables["/al2/n4"]).eq(undefined); - }); - }); - - cy.log("set componentIndex to 1"); - cy.get(cesc("#\\/m") + " textarea").type("{end}{backspace}1{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y1), - ); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y1), - ); - cy.get(cesc("#\\/al2\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n4") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(y1); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/n3"]).eq(undefined); - expect(stateVariables["/n4"]).eq(undefined); - expect(stateVariables["/al2/n1"].stateValues.value).eq(y1); - expect(stateVariables["/al2/n2"]).eq(undefined); - expect(stateVariables["/al2/n3"]).eq(undefined); - expect(stateVariables["/al2/n4"]).eq(undefined); - }); - }); - - cy.log("set propIndex to 3"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n4") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/n3"]).eq(undefined); - expect(stateVariables["/n4"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); - expect(stateVariables["/al2/n2"]).eq(undefined); - expect(stateVariables["/al2/n3"]).eq(undefined); - expect(stateVariables["/al2/n4"]).eq(undefined); - }); - }); - - cy.log("set propIndex to 1"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}1{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - cy.get(cesc("#\\/al2\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n4") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(x1); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/n3"]).eq(undefined); - expect(stateVariables["/n4"]).eq(undefined); - expect(stateVariables["/al2/n1"].stateValues.value).eq(x1); - expect(stateVariables["/al2/n2"]).eq(undefined); - expect(stateVariables["/al2/n3"]).eq(undefined); - expect(stateVariables["/al2/n4"]).eq(undefined); - }); - }); - - cy.log("set componentIndex to 3"); - cy.get(cesc("#\\/m") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n4") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/n3"]).eq(undefined); - expect(stateVariables["/n4"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); - expect(stateVariables["/al2/n2"]).eq(undefined); - expect(stateVariables["/al2/n3"]).eq(undefined); - expect(stateVariables["/al2/n4"]).eq(undefined); - }); - }); - - cy.log("set componentIndex to 2"); - cy.get(cesc("#\\/m") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n4") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(x2); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/n3"]).eq(undefined); - expect(stateVariables["/n4"]).eq(undefined); - expect(stateVariables["/al2/n1"].stateValues.value).eq(x2); - expect(stateVariables["/al2/n2"]).eq(undefined); - expect(stateVariables["/al2/n3"]).eq(undefined); - expect(stateVariables["/al2/n4"]).eq(undefined); - }); - }); - - cy.log("clear propIndex"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n4") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/n3"]).eq(undefined); - expect(stateVariables["/n4"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); - expect(stateVariables["/al2/n2"]).eq(undefined); - expect(stateVariables["/al2/n3"]).eq(undefined); - expect(stateVariables["/al2/n4"]).eq(undefined); - }); - }); - }); - - it("collect prop is case insensitive", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - (-3,1) - (-7,5) - - - - $_point1{name="p1a"} - (4,2) - - (, - ) - - - - - - - - -

Coordinates of points:

-

x-coordinates of points:

-

x-coordinates of points via a copy:

-

x-coordinates of points via extract:

-

Average of y-coordinates of points:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let x1 = -3, - y1 = 1; - let x2 = -7, - y2 = 5; - let x3 = 4, - y3 = 2; - - let coords1Text = ("(" + x1 + "," + y1 + ")").replace(/-/g, "−"); - let coords2Text = ("(" + x2 + "," + y2 + ")").replace(/-/g, "−"); - let coords3Text = ("(" + x3 + "," + y3 + ")").replace(/-/g, "−"); - let coords2tText = ("(" + y2 + "," + x2 + ")").replace(/-/g, "−"); - - let meany = (y1 + y2 + y1 + y3 + x2) / 5; - - cy.get(cesc("#\\/c1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(coords1Text); - }); - cy.get(cesc("#\\/c2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(coords2Text); - }); - cy.get(cesc("#\\/c3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(coords1Text); - }); - cy.get(cesc("#\\/c4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(coords3Text); - }); - cy.get(cesc("#\\/c5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(coords2tText); - }); - - cy.get(cesc("#\\/x1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(x1).replace(/-/, "−")); - }); - cy.get(cesc("#\\/x2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(x2).replace(/-/, "−")); - }); - cy.get(cesc("#\\/x3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(x1).replace(/-/, "−")); - }); - cy.get(cesc("#\\/x4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(x3).replace(/-/, "−")); - }); - cy.get(cesc("#\\/x5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(y2).replace(/-/, "−")); - }); - - cy.get(cesc("#\\/xc1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(x1).replace(/-/, "−")); - }); - cy.get(cesc("#\\/xc2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(x2).replace(/-/, "−")); - }); - cy.get(cesc("#\\/xc3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(x1).replace(/-/, "−")); - }); - cy.get(cesc("#\\/xc4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(x3).replace(/-/, "−")); - }); - cy.get(cesc("#\\/xc5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(y2).replace(/-/, "−")); - }); - - cy.get(cesc("#\\/xe1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(x1).replace(/-/, "−")); - }); - cy.get(cesc("#\\/xe2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(x2).replace(/-/, "−")); - }); - cy.get(cesc("#\\/xe3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(x1).replace(/-/, "−")); - }); - cy.get(cesc("#\\/xe4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(x3).replace(/-/, "−")); - }); - cy.get(cesc("#\\/xe5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(y2).replace(/-/, "−")); - }); - - cy.get(cesc("#\\/mean")) - .find(".mjx-mrow") - .invoke("text") - .then((text) => { - expect(text.trim()).equal(String(meany).replace(/-/, "−")); - }); - - cy.window().then(async (win) => { - let xs = [x1, x2, x1, x3, y2]; - let ys = [y1, y2, y1, y3, x2]; - let stateVariables = await win.returnAllStateVariables1(); - for (let i = 0; i < 5; i++) { - expect(stateVariables[`/q${i + 1}`].stateValues.xs[0]).eq( - xs[i], - ); - expect(stateVariables[`/q${i + 1}`].stateValues.xs[1]).eq( - ys[i], - ); - expect(stateVariables[`/qa${i + 1}`].stateValues.xs[0]).eq( - xs[i], - ); - expect(stateVariables[`/qa${i + 1}`].stateValues.xs[1]).eq( - ys[i], - ); - expect(stateVariables[`/c${i + 1}`].stateValues.value).eqls([ - "vector", - xs[i], - ys[i], - ]); - expect(stateVariables[`/x${i + 1}`].stateValues.value).eq( - xs[i], - ); - expect(stateVariables[`/xc${i + 1}`].stateValues.value).eq( - xs[i], - ); - expect(stateVariables[`/xe${i + 1}`].stateValues.value).eq( - xs[i], - ); - expect(stateVariables[`/y${i + 1}`].stateValues.value).eq( - ys[i], - ); - } - expect(stateVariables["/mean"].stateValues.value).eq(meany); - }); - }); - - it("collect from source that initially does not exist", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - (1,2) - (3,4) - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc2("#/bi")).click(); - - cy.get(cesc2("#/P1") + " .mjx-mrow").should("contain.text", "(1,2"); - cy.get(cesc2("#/P2") + " .mjx-mrow").should("contain.text", "(3,4"); - }); -}); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/copy.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/copy.cy.js index a77fb2f21..205f017a3 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/copy.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/copy.cy.js @@ -1,17678 +1,1445 @@ import { cesc, cesc2 } from "@doenet/utils"; -function nInDOM(n) { - if (n < 0) { - return `−${Math.abs(n)}`; - } else { - return String(n); - } -} - describe("Copy Tag Tests", function () { beforeEach(() => { cy.clearIndexedDB(); cy.visit("/"); }); - it("copy copies properties", () => { + it("copy uri two problems", () => { cy.window().then(async (win) => { win.postMessage( { doenetML: ` - a - x - - - x - - - (1,2) - - + Two problems + + + + `, }, "*", ); }); + cy.get(cesc("#\\/_title1")).should("have.text", "Two problems"); // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded + let problem1Version; + let animalOptions = ["cat", "dog", "mouse", "fish"]; + let soundOptions = ["meow", "woof", "squeak", "blub"]; - cy.log(`check properties`); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.modifyIndirectly).eq( - false, + cy.get(cesc2("#/problem1/_title1")).should( + "have.text", + "Animal sounds", + ); + + cy.get(cesc2("#/problem1/_p1")) + .invoke("text") + .then((text) => { + let titleOptions = animalOptions.map( + (x) => `What does the ${x} say?`, + ); + problem1Version = titleOptions.indexOf(text); + expect(problem1Version).not.eq(-1); + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let copy1Name = stateVariables["/problem1"].replacementOf; + let copy2Name = stateVariables["/problem2"].replacementOf; + expect(stateVariables[copy1Name].stateValues.cid).eq( + "bafkreifgmyjuw4m6odukznenshkyfupp3egx6ep3jgnlo747d6s5v7nznu", + ); + expect(stateVariables[copy1Name].stateValues.doenetId).eq( + "abcdefg", + ); + expect(stateVariables[copy2Name].stateValues.cid).eq( + "bafkreide4mismb45mxved2ibfh5jnj75kty7vjz7w6zo7goyxpwr2e7wti", + ); + expect(stateVariables[copy2Name].stateValues.doenetId).eq( + "hijklmnop", + ); + }); + }); + + cy.log(`select correct answer for problem 1`).then(() => { + let animal = animalOptions[problem1Version]; + let sound = soundOptions[problem1Version]; + cy.get(cesc2("#/problem1/_choiceinput1")) + .contains(sound) + .click({ force: true }); + cy.get(cesc2("#/problem1/_choiceinput1_submit")).click(); + cy.get(cesc2("#/problem1/_choiceinput1_correct")).should( + "be.visible", ); - expect(stateVariables["/a"].stateValues.modifyIndirectly).eq(false); - expect(stateVariables["/b"].stateValues.modifyIndirectly).eq(false); - expect(stateVariables["/_math2"].stateValues.modifyIndirectly).eq( - true, + cy.get(cesc2("#/problem1/_choiceinput1_incorrect")).should( + "not.exist", ); - expect(stateVariables["/c"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/d"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/_point1"].stateValues.label).eq("A"); - expect(stateVariables["/e"].stateValues.label).eq("A"); - expect(stateVariables["/f"].stateValues.label).eq("A"); - }); - }); - - it("copy copies properties, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x - $_math1{name="a"} - $a{name="b"} - x - $_math2{name="c"} - $c{name="d"} - (1,2) - $_point1{name="e"} - $e{name="f"} - `, - }, - "*", + cy.get(cesc2("#/problem1/_feedback1")).should( + "have.text", + `That's right, the ${animal} goes ${sound}!`, ); + cy.get(cesc2("#/problem1/_feedback2")).should("not.exist"); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log(`check properties`); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.modifyIndirectly).eq( - false, + cy.log(`select incorrect answer for problem 1`).then(() => { + let incorrectInd = (problem1Version + 1) % 4; + let sound = soundOptions[incorrectInd]; + cy.get(cesc2("#/problem1/_choiceinput1")) + .contains(sound) + .click({ force: true }); + cy.get(cesc2("#/problem1/_choiceinput1_submit")).click(); + cy.get(cesc2("#/problem1/_choiceinput1_correct")).should( + "not.exist", ); - expect(stateVariables["/a"].stateValues.modifyIndirectly).eq(false); - expect(stateVariables["/b"].stateValues.modifyIndirectly).eq(false); - expect(stateVariables["/_math2"].stateValues.modifyIndirectly).eq( - true, + cy.get(cesc2("#/problem1/_choiceinput1_incorrect")).should( + "be.visible", ); - expect(stateVariables["/c"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/d"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/_point1"].stateValues.label).eq("A"); - expect(stateVariables["/e"].stateValues.label).eq("A"); - expect(stateVariables["/f"].stateValues.label).eq("A"); - }); - }); - - it("copy copies properties, with copySource", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x - x - - - - - (1,2) - - - `, - }, - "*", + cy.get(cesc2("#/problem1/_feedback1")).should("not.exist"); + cy.get(cesc2("#/problem1/_feedback2")).should( + "have.text", + `Try again.`, ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded + cy.get(cesc2("#/problem2/_title1")).should( + "have.text", + "Derivative problem", + ); - cy.log(`check properties`); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.modifyIndirectly).eq( - false, + let mathinputName = + stateVariables["/problem2/_answer1"].stateValues + .inputChildren[0].componentName; + let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; + let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); + let mathinputCorrectAnchor = cesc2( + "#" + mathinputName + "_correct", ); - expect(stateVariables["/a"].stateValues.modifyIndirectly).eq(false); - expect(stateVariables["/b"].stateValues.modifyIndirectly).eq(false); - expect(stateVariables["/_math2"].stateValues.modifyIndirectly).eq( - true, + let mathinputIncorrectAnchor = cesc2( + "#" + mathinputName + "_incorrect", ); - expect(stateVariables["/c"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/d"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/_point1"].stateValues.label).eq("A"); - expect(stateVariables["/e"].stateValues.label).eq("A"); - expect(stateVariables["/f"].stateValues.label).eq("A"); + + cy.log(`enter incorrect answer for problem 2`); + cy.get(mathinputAnchor).type("2y{enter}", { force: true }); + cy.get(mathinputSubmitAnchor).should("not.exist"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("be.visible"); + + cy.log(`enter correct answer for problem 2`); + cy.get(mathinputAnchor).type("{end}{backspace}x", { force: true }); + cy.get(mathinputSubmitAnchor).should("be.visible"); + cy.get(mathinputAnchor).type("{enter}", { force: true }); + cy.get(mathinputSubmitAnchor).should("not.exist"); + cy.get(mathinputCorrectAnchor).should("be.visible"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); }); }); - it("copy overwrites properties", () => { + it("copy uri two problems, with copyFromUri", () => { cy.window().then(async (win) => { win.postMessage( { doenetML: ` - a - x - - - - - - - - (1,2) - - - - - - - - - + Two problems + + + + `, }, "*", ); }); + cy.get(cesc("#\\/_title1")).should("have.text", "Two problems"); // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded + let problem1Version; + let animalOptions = ["cat", "dog", "mouse", "fish"]; + let soundOptions = ["meow", "woof", "squeak", "blub"]; - cy.log(`check properties`); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.modifyIndirectly).eq( - false, - ); - expect(stateVariables["/r1"].stateValues.modifyIndirectly).eq( - false, + cy.get(cesc2("#/problem1/_title1")).should( + "have.text", + "Animal sounds", + ); + + cy.get(cesc2("#/problem1/_p1")) + .invoke("text") + .then((text) => { + let titleOptions = animalOptions.map( + (x) => `What does the ${x} say?`, + ); + problem1Version = titleOptions.indexOf(text); + expect(problem1Version).not.eq(-1); + }); + + cy.log(`select correct answer for problem 1`).then(() => { + let animal = animalOptions[problem1Version]; + let sound = soundOptions[problem1Version]; + cy.get(cesc2("#/problem1/_choiceinput1")) + .contains(sound) + .click({ force: true }); + cy.get(cesc2("#/problem1/_choiceinput1_submit")).click(); + cy.get(cesc2("#/problem1/_choiceinput1_correct")).should( + "be.visible", ); - expect(stateVariables["/r2"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/r3"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/r4"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/r5"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/r6"].stateValues.modifyIndirectly).eq( - false, + cy.get(cesc2("#/problem1/_choiceinput1_incorrect")).should( + "not.exist", ); - expect(stateVariables["/r7"].stateValues.modifyIndirectly).eq( - false, + cy.get(cesc2("#/problem1/_feedback1")).should( + "have.text", + `That's right, the ${animal} goes ${sound}!`, ); - - expect(stateVariables["/A"].stateValues.label).eq("A"); - expect(stateVariables["/A2"].stateValues.label).eq("A"); - expect(stateVariables["/B"].stateValues.label).eq("B"); - expect(stateVariables["/B2"].stateValues.label).eq("A"); - expect(stateVariables["/C"].stateValues.label).eq("C"); - expect(stateVariables["/C2"].stateValues.label).eq("B"); - expect(stateVariables["/D"].stateValues.label).eq("D"); - expect(stateVariables["/D2"].stateValues.label).eq("C"); - expect(stateVariables["/D5"].stateValues.label).eq("D5"); - expect(stateVariables["/D6"].stateValues.label).eq("B"); + cy.get(cesc2("#/problem1/_feedback2")).should("not.exist"); }); - }); - it("copy overwrites properties, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x - $_math1{name="r1" } - $_math1{name="r2" modifyIndirectly="true" } - $r1{name="r3" modifyIndirectly="true" } - $r2{name="r4" } - $r3{name="r5" } - $r2{name="r6" modifyIndirectly="false" } - $r3{name="r7" modifyIndirectly="false" } - (1,2) - $A{name="A2" } - $A{name="B" labelIsName } - $A2{name="B2" } - $B{name="C" labelIsName } - $B{name="C2" } - $C{name="D" labelIsName } - $C{name="D2" } - $C2{name="D5" labelIsName } - $C2{name="D6" } - `, - }, - "*", + cy.log(`select incorrect answer for problem 1`).then(() => { + let incorrectInd = (problem1Version + 1) % 4; + let sound = soundOptions[incorrectInd]; + cy.get(cesc2("#/problem1/_choiceinput1")) + .contains(sound) + .click({ force: true }); + cy.get(cesc2("#/problem1/_choiceinput1_submit")).click(); + cy.get(cesc2("#/problem1/_choiceinput1_correct")).should( + "not.exist", + ); + cy.get(cesc2("#/problem1/_choiceinput1_incorrect")).should( + "be.visible", + ); + cy.get(cesc2("#/problem1/_feedback1")).should("not.exist"); + cy.get(cesc2("#/problem1/_feedback2")).should( + "have.text", + `Try again.`, ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded + cy.get(cesc2("#/problem2/_title1")).should( + "have.text", + "Derivative problem", + ); - cy.log(`check properties`); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.modifyIndirectly).eq( - false, - ); - expect(stateVariables["/r1"].stateValues.modifyIndirectly).eq( - false, - ); - expect(stateVariables["/r2"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/r3"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/r4"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/r5"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/r6"].stateValues.modifyIndirectly).eq( - false, + let mathinputName = + stateVariables["/problem2/_answer1"].stateValues + .inputChildren[0].componentName; + let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; + let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); + let mathinputCorrectAnchor = cesc2( + "#" + mathinputName + "_correct", ); - expect(stateVariables["/r7"].stateValues.modifyIndirectly).eq( - false, + let mathinputIncorrectAnchor = cesc2( + "#" + mathinputName + "_incorrect", ); - expect(stateVariables["/A"].stateValues.label).eq("A"); - expect(stateVariables["/A2"].stateValues.label).eq("A"); - expect(stateVariables["/B"].stateValues.label).eq("B"); - expect(stateVariables["/B2"].stateValues.label).eq("A"); - expect(stateVariables["/C"].stateValues.label).eq("C"); - expect(stateVariables["/C2"].stateValues.label).eq("B"); - expect(stateVariables["/D"].stateValues.label).eq("D"); - expect(stateVariables["/D2"].stateValues.label).eq("C"); - expect(stateVariables["/D5"].stateValues.label).eq("D5"); - expect(stateVariables["/D6"].stateValues.label).eq("B"); + cy.log(`enter incorrect answer for problem 2`); + cy.get(mathinputAnchor).type("2y{enter}", { force: true }); + cy.get(mathinputSubmitAnchor).should("not.exist"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("be.visible"); + + cy.log(`enter correct answer for problem 2`); + cy.get(mathinputAnchor).type("{end}{backspace}x", { force: true }); + cy.get(mathinputSubmitAnchor).should("be.visible"); + cy.get(mathinputAnchor).type("{enter}", { force: true }); + cy.get(mathinputSubmitAnchor).should("not.exist"); + cy.get(mathinputCorrectAnchor).should("be.visible"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); }); }); - it("copy overwrites properties, with copySource", () => { + it("copy uri two problems, with copyFromUri, change titles, add content, change attribute", () => { cy.window().then(async (win) => { win.postMessage( { doenetML: ` - a - x - - - - - - - + Two problems + + + Extra animal sounds + +

New content at bottom

+
+ + + Derivative with second derivative + +

What is the second derivative of ? + + + $(problem2/_derivative1) + + +

+
- (1,2) - (1,2) - - - - - - - - - - - - - - - - - - - - - - - - - - +

End paragraph

`, }, "*", ); }); + cy.get(cesc("#\\/_title1")).should("have.text", "Two problems"); // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded + let problem1Version; + let animalOptions = ["cat", "dog", "mouse", "fish"]; + let soundOptions = ["meow", "woof", "squeak", "blub"]; - cy.log(`check properties`); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.modifyIndirectly).eq( - false, - ); - expect(stateVariables["/r1"].stateValues.modifyIndirectly).eq( - false, - ); - expect(stateVariables["/r2"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/r3"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/r4"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/r5"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/r6"].stateValues.modifyIndirectly).eq( - false, - ); - expect(stateVariables["/r7"].stateValues.modifyIndirectly).eq( - false, - ); - - expect(stateVariables["/A"].stateValues.label).eq("A"); - expect(stateVariables["/A2"].stateValues.label).eq("A"); - expect(stateVariables["/A3"].stateValues.label).eq("A"); - expect(stateVariables["/A4"].stateValues.label).eq("A"); - expect(stateVariables["/B"].stateValues.label).eq("B"); - expect(stateVariables["/B2"].stateValues.label).eq("A"); - expect(stateVariables["/B3"].stateValues.label).eq("B"); - expect(stateVariables["/B4"].stateValues.label).eq("B4"); - expect(stateVariables["/B5"].stateValues.label).eq("A"); - expect(stateVariables["/B6"].stateValues.label).eq("B"); - expect(stateVariables["/C"].stateValues.label).eq("C"); - expect(stateVariables["/C2"].stateValues.label).eq("B"); - expect(stateVariables["/C3"].stateValues.label).eq("C"); - expect(stateVariables["/C4"].stateValues.label).eq("C4"); - expect(stateVariables["/C5"].stateValues.label).eq("A"); - expect(stateVariables["/C6"].stateValues.label).eq("C"); - expect(stateVariables["/C7"].stateValues.label).eq("C7"); - expect(stateVariables["/C8"].stateValues.label).eq("B"); - expect(stateVariables["/C9"].stateValues.label).eq("C"); - expect(stateVariables["/C10"].stateValues.label).eq("C10"); - expect(stateVariables["/C11"].stateValues.label).eq("B4"); - expect(stateVariables["/C12"].stateValues.label).eq("C"); - expect(stateVariables["/C13"].stateValues.label).eq("C13"); - expect(stateVariables["/C14"].stateValues.label).eq("A"); - expect(stateVariables["/C15"].stateValues.label).eq("C"); - expect(stateVariables["/C16"].stateValues.label).eq("C16"); - expect(stateVariables["/C17"].stateValues.label).eq("B"); - expect(stateVariables["/C18"].stateValues.label).eq("C"); - }); - }); + cy.get(cesc2("#/problem1/_title1")).should("not.exist"); + cy.get(cesc2("#/_title2")).should("have.text", "Extra animal sounds"); + cy.get(cesc2("#/_p1")).should("have.text", "New content at bottom"); + cy.get(cesc2("#/_p3")).should("have.text", "End paragraph"); - it("copy overwrites properties, decode XML entities", () => { cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x - - - - - - - - - - `, - }, - "*", + let stateVariables = await win.returnAllStateVariables1(); + expect(stateVariables["/problem1"].stateValues.title).eq( + "Extra animal sounds", ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded + cy.get(cesc2("#/problem1/_p1")) + .invoke("text") + .then((text) => { + let titleOptions = animalOptions.map( + (x) => `What does the ${x} say?`, + ); + problem1Version = titleOptions.indexOf(text); + expect(problem1Version).not.eq(-1); + }); - cy.log(`check properties`); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.modifyIndirectly).eq( - false, - ); - expect(stateVariables["/r1"].stateValues.modifyIndirectly).eq( - false, + cy.log(`select correct answer for problem 1`).then(() => { + let animal = animalOptions[problem1Version]; + let sound = soundOptions[problem1Version]; + cy.get(cesc2("#/problem1/_choiceinput1")) + .contains(sound) + .click({ force: true }); + cy.get(cesc2("#/problem1/_choiceinput1_submit")).click(); + cy.get(cesc2("#/problem1/_choiceinput1_correct")).should( + "be.visible", ); - expect(stateVariables["/r2"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/r3"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/r4"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/r5"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/r6"].stateValues.modifyIndirectly).eq( - false, + cy.get(cesc2("#/problem1/_choiceinput1_incorrect")).should( + "not.exist", ); - expect(stateVariables["/r7"].stateValues.modifyIndirectly).eq( - false, + cy.get(cesc2("#/problem1/_feedback1")).should( + "have.text", + `That's right, the ${animal} goes ${sound}!`, ); + cy.get(cesc2("#/problem1/_feedback2")).should("not.exist"); }); - }); - - it("copy overwrites properties, decode XML entities, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x - $_math1{name="r1" } - $_math1{name="r2" modifyIndirectly="3<4" } - $r1{name="r3" modifyIndirectly="3<4" } - $r2{name="r4" } - $r3{name="r5" } - $r2{name="r6" modifyIndirectly="3>4" } - $r3{name="r7" modifyIndirectly="3>4" } - - `, - }, - "*", + cy.log(`select incorrect answer for problem 1`).then(() => { + let incorrectInd = (problem1Version + 1) % 4; + let sound = soundOptions[incorrectInd]; + cy.get(cesc2("#/problem1/_choiceinput1")) + .contains(sound) + .click({ force: true }); + cy.get(cesc2("#/problem1/_choiceinput1_submit")).click(); + cy.get(cesc2("#/problem1/_choiceinput1_correct")).should( + "not.exist", + ); + cy.get(cesc2("#/problem1/_choiceinput1_incorrect")).should( + "be.visible", + ); + cy.get(cesc2("#/problem1/_feedback1")).should("not.exist"); + cy.get(cesc2("#/problem1/_feedback2")).should( + "have.text", + `Try again.`, ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded + cy.get(cesc2("#/problem2/_title1")).should("not.exist"); + cy.get(cesc2("#/_title3")).should( + "have.text", + "Derivative with second derivative", + ); - cy.log(`check properties`); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.modifyIndirectly).eq( - false, - ); - expect(stateVariables["/r1"].stateValues.modifyIndirectly).eq( - false, - ); - expect(stateVariables["/r2"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/r3"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/r4"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/r5"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/r6"].stateValues.modifyIndirectly).eq( - false, - ); - expect(stateVariables["/r7"].stateValues.modifyIndirectly).eq( - false, + let mathinputName = + stateVariables["/problem2/_answer1"].stateValues + .inputChildren[0].componentName; + let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; + + let mathinput2Name = + stateVariables["/_answer1"].stateValues.inputChildren[0] + .componentName; + let mathinput2Anchor = cesc2("#" + mathinput2Name) + " textarea"; + + expect(stateVariables["/problem2"].stateValues.title).eq( + "Derivative with second derivative", ); + + cy.log(`enter incorrect answer for problem 2`); + cy.get(mathinputAnchor).type("2y{enter}", { force: true }); + cy.get(cesc2("#/problem2_submit")).click(); + cy.get(cesc2("#/problem2_incorrect")).should("be.visible"); + + cy.log(`enter correct answer for problem 2`); + cy.get(mathinputAnchor).type("{end}{backspace}x", { force: true }); + cy.get(cesc2("#/problem2_submit")).click(); + cy.get(cesc2("#/problem2_partial")).should("contain.text", "50%"); + + cy.log(`enter incorrect answer for problem 2, part 2`); + cy.get(mathinput2Anchor).type("3{enter}", { force: true }); + cy.get(cesc2("#/problem2_submit")).click(); + cy.get(cesc2("#/problem2_partial")).should("contain.text", "50%"); + + cy.log(`enter correct answer for problem 2, part 2`); + cy.get(mathinput2Anchor).type("{end}{backspace}2", { force: true }); + cy.get(cesc2("#/problem2_submit")).click(); + cy.get(cesc2("#/problem2_correct")).should("be.visible"); }); }); - it("copy overwrites properties, decode XML entities, with copySource", () => { + it("copy uri two problems, with copyFromUri, newNamespace change titles, add content, change attribute", () => { cy.window().then(async (win) => { win.postMessage( { doenetML: ` - a - x - - - - - - - + Two problems + + + Extra animal sounds + +

New content at bottom

+
+ + + Derivative with second derivative + +

What is the second derivative of ? + + + $_derivative1 + + +

+
+

End paragraph

`, }, "*", ); }); + cy.get(cesc("#\\/_title1")).should("have.text", "Two problems"); // to wait for page to load + + let problem1Version; + let animalOptions = ["cat", "dog", "mouse", "fish"]; + let soundOptions = ["meow", "woof", "squeak", "blub"]; - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded + cy.get(cesc2("#/problem1/_title1")).should("not.exist"); + cy.get(cesc2("#/problem1/_title2")).should( + "have.text", + "Extra animal sounds", + ); + cy.get(cesc2("#/problem1/_p4")).should( + "have.text", + "New content at bottom", + ); + cy.get(cesc2("#/_p1")).should("have.text", "End paragraph"); - cy.log(`check properties`); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.modifyIndirectly).eq( - false, + expect(stateVariables["/problem1"].stateValues.title).eq( + "Extra animal sounds", ); - expect(stateVariables["/r1"].stateValues.modifyIndirectly).eq( - false, + }); + + cy.get(cesc2("#/problem1/_p1")) + .invoke("text") + .then((text) => { + let titleOptions = animalOptions.map( + (x) => `What does the ${x} say?`, + ); + problem1Version = titleOptions.indexOf(text); + expect(problem1Version).not.eq(-1); + }); + + cy.log(`select correct answer for problem 1`).then(() => { + let animal = animalOptions[problem1Version]; + let sound = soundOptions[problem1Version]; + cy.get(cesc2("#/problem1/_choiceinput1")) + .contains(sound) + .click({ force: true }); + cy.get(cesc2("#/problem1/_choiceinput1_submit")).click(); + cy.get(cesc2("#/problem1/_choiceinput1_correct")).should( + "be.visible", ); - expect(stateVariables["/r2"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/r3"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/r4"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/r5"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/r6"].stateValues.modifyIndirectly).eq( - false, + cy.get(cesc2("#/problem1/_choiceinput1_incorrect")).should( + "not.exist", ); - expect(stateVariables["/r7"].stateValues.modifyIndirectly).eq( - false, + cy.get(cesc2("#/problem1/_feedback1")).should( + "have.text", + `That's right, the ${animal} goes ${sound}!`, ); + cy.get(cesc2("#/problem1/_feedback2")).should("not.exist"); }); - }); - it("copy props", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x - - - - - - - - (1,2) - - - - - - - `, - }, - "*", + cy.log(`select incorrect answer for problem 1`).then(() => { + let incorrectInd = (problem1Version + 1) % 4; + let sound = soundOptions[incorrectInd]; + cy.get(cesc2("#/problem1/_choiceinput1")) + .contains(sound) + .click({ force: true }); + cy.get(cesc2("#/problem1/_choiceinput1_submit")).click(); + cy.get(cesc2("#/problem1/_choiceinput1_correct")).should( + "not.exist", + ); + cy.get(cesc2("#/problem1/_choiceinput1_incorrect")).should( + "be.visible", + ); + cy.get(cesc2("#/problem1/_feedback1")).should("not.exist"); + cy.get(cesc2("#/problem1/_feedback2")).should( + "have.text", + `Try again.`, ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded + cy.get(cesc2("#/problem2/_title1")).should("not.exist"); + cy.get(cesc2("#/problem2/_title2")).should( + "have.text", + "Derivative with second derivative", + ); - cy.log(`check properties`); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/x"].stateValues.modifyIndirectly).eq(false); - expect(stateVariables["/x"].stateValues.hidden).eq(true); - // modifyIndirectly attribute is copied (as it has propagateToProps=true) - expect(stateVariables["/mr"].stateValues.modifyIndirectly).eq( - false, - ); - // hide attribute is not copied (default behavior) - expect(stateVariables["/mr"].stateValues.hidden).eq(false); - expect(stateVariables["/mr"].stateValues.value).eq(false); + let mathinputName = + stateVariables["/problem2/_answer1"].stateValues + .inputChildren[0].componentName; + let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - // modifyIndirectly is overwritten - expect(stateVariables["/mr2"].stateValues.modifyIndirectly).eq( - true, - ); - expect(stateVariables["/mr2"].stateValues.hidden).eq(false); - expect(stateVariables["/mr2"].stateValues.value).eq(false); + let mathinput2Name = + stateVariables["/problem2/_answer2"].stateValues + .inputChildren[0].componentName; + let mathinput2Anchor = cesc2("#" + mathinput2Name) + " textarea"; - // modifyIndirectly attribute is copied (as it has propagateToProps=true) - expect(stateVariables["/frmt"].stateValues.modifyIndirectly).eq( - false, + expect(stateVariables["/problem2"].stateValues.title).eq( + "Derivative with second derivative", ); - // hide attribute is not copied (default behavior) - expect(stateVariables["/frmt"].stateValues.hidden).eq(false); - expect(stateVariables["/frmt"].stateValues.value).eq("text"); - expect(stateVariables["/frmt2"].stateValues.modifyIndirectly).eq( - false, - ); - expect(stateVariables["/frmt2"].stateValues.hidden).eq(true); - expect(stateVariables["/frmt2"].stateValues.value).eq("text"); + cy.log(`enter incorrect answer for problem 2`); + cy.get(mathinputAnchor).type("2y{enter}", { force: true }); + cy.get(cesc2("#/problem2_submit")).click(); + cy.get(cesc2("#/problem2_incorrect")).should("be.visible"); - // all attributes copied when don't use prop - expect(stateVariables["/frmt3"].stateValues.modifyIndirectly).eq( - false, - ); - expect(stateVariables["/frmt3"].stateValues.value).eq("text"); - expect(stateVariables["/frmt3"].stateValues.hidden).eq(true); + cy.log(`enter correct answer for problem 2`); + cy.get(mathinputAnchor).type("{end}{backspace}x", { force: true }); + cy.get(cesc2("#/problem2_submit")).click(); + cy.get(cesc2("#/problem2_partial")).should("contain.text", "50%"); - expect(stateVariables["/A"].stateValues.label).eq("A"); - expect(stateVariables["/cA"].stateValues.value).eqls([ - "vector", - 1, - 2, - ]); - expect(stateVariables["/l"].stateValues.value).eq( - "\\left( 1, 2 \\right)", - ); - expect(stateVariables["/l"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/lmr"].stateValues.value).eq( - "\\left( 1, 2 \\right)", - ); - expect(stateVariables["/lmr"].stateValues.modifyIndirectly).eq( - false, - ); - expect(stateVariables["/A2"].stateValues.label).eq("A"); - expect(stateVariables["/cA2"].stateValues.value).eqls([ - "vector", - 1, - 2, - ]); - expect(stateVariables["/l2"].stateValues.value).eq( - "\\left( 1, 2 \\right)", - ); + cy.log(`enter incorrect answer for problem 2, part 2`); + cy.get(mathinput2Anchor).type("3{enter}", { force: true }); + cy.get(cesc2("#/problem2_submit")).click(); + cy.get(cesc2("#/problem2_partial")).should("contain.text", "50%"); + + cy.log(`enter correct answer for problem 2, part 2`); + cy.get(mathinput2Anchor).type("{end}{backspace}2", { force: true }); + cy.get(cesc2("#/problem2_submit")).click(); + cy.get(cesc2("#/problem2_correct")).should("be.visible"); }); }); - it("copy props, dot notation", () => { + it("copy uri two problems, change attribute but cannot change titles or add content without copyFromUri", () => { cy.window().then(async (win) => { win.postMessage( { doenetML: ` - a - x - - + Two problems - - - + + Extra animal sounds + +

New content at bottom

+
+ + + Derivative with second derivative + +

What is the second derivative of ? + + + $(problem2/_derivative1) + + +

+
+

End paragraph

- (1,2) - - - - - - `, }, "*", ); }); + cy.get(cesc("#\\/_title1")).should("have.text", "Two problems"); // to wait for page to load + + let problem1Version; + let animalOptions = ["cat", "dog", "mouse", "fish"]; + let soundOptions = ["meow", "woof", "squeak", "blub"]; - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded + cy.get(cesc2("#/problem1/_title1")).should( + "have.text", + "Animal sounds", + ); + cy.get(cesc2("#/_title2")).should("not.exist"); + cy.get(cesc2("#/_p1")).should("not.exist"); + cy.get(cesc2("#/_p3")).should("have.text", "End paragraph"); - cy.log(`check properties`); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/x"].stateValues.modifyIndirectly).eq(false); - expect(stateVariables["/x"].stateValues.hidden).eq(true); - // modifyIndirectly attribute is copied (as it has propagateToProps=true) - expect(stateVariables["/mr"].stateValues.modifyIndirectly).eq( - false, + expect(stateVariables["/problem1"].stateValues.title).eq( + "Animal sounds", ); - // hide attribute is not copied (default behavior) - expect(stateVariables["/mr"].stateValues.hidden).eq(false); - expect(stateVariables["/mr"].stateValues.value).eq(false); + }); - // modifyIndirectly is overwritten - expect(stateVariables["/mr2"].stateValues.modifyIndirectly).eq( - true, - ); - expect(stateVariables["/mr2"].stateValues.hidden).eq(false); - expect(stateVariables["/mr2"].stateValues.value).eq(false); + cy.get(cesc2("#/problem1/_p1")) + .invoke("text") + .then((text) => { + let titleOptions = animalOptions.map( + (x) => `What does the ${x} say?`, + ); + problem1Version = titleOptions.indexOf(text); + expect(problem1Version).not.eq(-1); + }); - // modifyIndirectly attribute is copied (as it has propagateToProps=true) - expect(stateVariables["/frmt"].stateValues.modifyIndirectly).eq( - false, + cy.log(`select correct answer for problem 1`).then(() => { + let animal = animalOptions[problem1Version]; + let sound = soundOptions[problem1Version]; + cy.get(cesc2("#/problem1/_choiceinput1")) + .contains(sound) + .click({ force: true }); + cy.get(cesc2("#/problem1/_choiceinput1_submit")).click(); + cy.get(cesc2("#/problem1/_choiceinput1_correct")).should( + "be.visible", ); - // hide attribute is not copied (default behavior) - expect(stateVariables["/frmt"].stateValues.hidden).eq(false); - expect(stateVariables["/frmt"].stateValues.value).eq("text"); - - expect(stateVariables["/frmt2"].stateValues.modifyIndirectly).eq( - false, + cy.get(cesc2("#/problem1/_choiceinput1_incorrect")).should( + "not.exist", ); - expect(stateVariables["/frmt2"].stateValues.hidden).eq(true); - expect(stateVariables["/frmt2"].stateValues.value).eq("text"); - - // all attributes copied when don't use prop - expect(stateVariables["/frmt3"].stateValues.modifyIndirectly).eq( - false, + cy.get(cesc2("#/problem1/_feedback1")).should( + "have.text", + `That's right, the ${animal} goes ${sound}!`, ); - expect(stateVariables["/frmt3"].stateValues.value).eq("text"); - expect(stateVariables["/frmt3"].stateValues.hidden).eq(true); + cy.get(cesc2("#/problem1/_feedback2")).should("not.exist"); + }); - expect(stateVariables["/A"].stateValues.label).eq("A"); - expect(stateVariables["/cA"].stateValues.value).eqls([ - "vector", - 1, - 2, - ]); - expect(stateVariables["/l"].stateValues.value).eq( - "\\left( 1, 2 \\right)", - ); - expect(stateVariables["/l"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/lmr"].stateValues.value).eq( - "\\left( 1, 2 \\right)", - ); - expect(stateVariables["/lmr"].stateValues.modifyIndirectly).eq( - false, + cy.log(`select incorrect answer for problem 1`).then(() => { + let incorrectInd = (problem1Version + 1) % 4; + let sound = soundOptions[incorrectInd]; + cy.get(cesc2("#/problem1/_choiceinput1")) + .contains(sound) + .click({ force: true }); + cy.get(cesc2("#/problem1/_choiceinput1_submit")).click(); + cy.get(cesc2("#/problem1/_choiceinput1_correct")).should( + "not.exist", ); - expect(stateVariables["/A2"].stateValues.label).eq("A"); - expect(stateVariables["/cA2"].stateValues.value).eqls([ - "vector", - 1, - 2, - ]); - expect(stateVariables["/l2"].stateValues.value).eq( - "\\left( 1, 2 \\right)", + cy.get(cesc2("#/problem1/_choiceinput1_incorrect")).should( + "be.visible", ); - }); - }); - - it("copy props, dot notation, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x - $(x.modifyIndirectly{assignNames="mr" }) - $(x.modifyIndirectly{assignNames="mr2" modifyIndirectly="true" }) - - $(x.format{assignNames="frmt" }) - $(x.format{assignNames="frmt2" hide }) - $frmt{name="frmt3" hide } - - (1,2) - $(A.coords{assignNames="cA" }) - $(cA.latex{assignNames="l" }) - $(cA.latex{assignNames="lmr" modifyIndirectly="false" }) - $A{name="A2" } - $(A2.coords{assignNames="cA2" }) - $(cA2.latex{assignNames="l2" }) - `, - }, - "*", + cy.get(cesc2("#/problem1/_feedback1")).should("not.exist"); + cy.get(cesc2("#/problem1/_feedback2")).should( + "have.text", + `Try again.`, ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded + cy.get(cesc2("#/problem2/_title1")).should( + "have.text", + "Derivative problem", + ); + cy.get(cesc2("#/_title3")).should("not.exist"); - cy.log(`check properties`); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/x"].stateValues.modifyIndirectly).eq(false); - expect(stateVariables["/x"].stateValues.hidden).eq(true); - // modifyIndirectly attribute is copied (as it has propagateToProps=true) - expect(stateVariables["/mr"].stateValues.modifyIndirectly).eq( - false, - ); - // hide attribute is not copied (default behavior) - expect(stateVariables["/mr"].stateValues.hidden).eq(false); - expect(stateVariables["/mr"].stateValues.value).eq(false); - - // modifyIndirectly is overwritten - expect(stateVariables["/mr2"].stateValues.modifyIndirectly).eq( - true, - ); - expect(stateVariables["/mr2"].stateValues.hidden).eq(false); - expect(stateVariables["/mr2"].stateValues.value).eq(false); + let mathinputName = + stateVariables["/problem2/_answer1"].stateValues + .inputChildren[0].componentName; + let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - // modifyIndirectly attribute is copied (as it has propagateToProps=true) - expect(stateVariables["/frmt"].stateValues.modifyIndirectly).eq( - false, - ); - // hide attribute is not copied (default behavior) - expect(stateVariables["/frmt"].stateValues.hidden).eq(false); - expect(stateVariables["/frmt"].stateValues.value).eq("text"); + expect(stateVariables["/_answer1"]).eq(undefined); - expect(stateVariables["/frmt2"].stateValues.modifyIndirectly).eq( - false, + expect(stateVariables["/problem2"].stateValues.title).eq( + "Derivative problem", ); - expect(stateVariables["/frmt2"].stateValues.hidden).eq(true); - expect(stateVariables["/frmt2"].stateValues.value).eq("text"); - // all attributes copied when don't use prop - expect(stateVariables["/frmt3"].stateValues.modifyIndirectly).eq( - false, - ); - expect(stateVariables["/frmt3"].stateValues.value).eq("text"); - expect(stateVariables["/frmt3"].stateValues.hidden).eq(true); + cy.log(`enter incorrect answer for problem 2`); + cy.get(mathinputAnchor).type("2y{enter}", { force: true }); + cy.get(cesc2("#/problem2_submit")).click(); + cy.get(cesc2("#/problem2_incorrect")).should("be.visible"); - expect(stateVariables["/A"].stateValues.label).eq("A"); - expect(stateVariables["/cA"].stateValues.value).eqls([ - "vector", - 1, - 2, - ]); - expect(stateVariables["/l"].stateValues.value).eq( - "\\left( 1, 2 \\right)", - ); - expect(stateVariables["/l"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/lmr"].stateValues.value).eq( - "\\left( 1, 2 \\right)", - ); - expect(stateVariables["/lmr"].stateValues.modifyIndirectly).eq( - false, - ); - expect(stateVariables["/A2"].stateValues.label).eq("A"); - expect(stateVariables["/cA2"].stateValues.value).eqls([ - "vector", - 1, - 2, - ]); - expect(stateVariables["/l2"].stateValues.value).eq( - "\\left( 1, 2 \\right)", - ); + cy.log(`enter correct answer for problem 2`); + cy.get(mathinputAnchor).type("{end}{backspace}x", { force: true }); + cy.get(cesc2("#/problem2_submit")).click(); + cy.get(cesc2("#/problem2_correct")).should("be.visible"); }); }); - it("copy props, with copySource", () => { + it("copy uri containing copy uri of two problems", () => { cy.window().then(async (win) => { win.postMessage( { doenetML: ` - a - x - - - - - - + Four problems - (1,2) - - - - - - + + + `, }, "*", ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded + cy.get(cesc("#\\/_title1")).should("have.text", "Four problems"); // to wait for page to load - cy.log(`check properties`); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/x"].stateValues.modifyIndirectly).eq(false); - expect(stateVariables["/x"].stateValues.hidden).eq(true); - // modifyIndirectly attribute is copied (as it has propagateToProps=true) - expect(stateVariables["/mr"].stateValues.modifyIndirectly).eq( - false, - ); - // hide attribute is not copied (default behavior) - expect(stateVariables["/mr"].stateValues.hidden).eq(false); - expect(stateVariables["/mr"].stateValues.value).eq(false); + let problem1Version; + let animalOptions = ["cat", "dog", "mouse", "fish"]; + let soundOptions = ["meow", "woof", "squeak", "blub"]; - // modifyIndirectly is overwritten - expect(stateVariables["/mr2"].stateValues.modifyIndirectly).eq( - true, - ); - expect(stateVariables["/mr2"].stateValues.hidden).eq(false); - expect(stateVariables["/mr2"].stateValues.value).eq(false); + cy.get(cesc2("#/problem12/problem1/_p1")) + .invoke("text") + .then((text) => { + let titleOptions = animalOptions.map( + (x) => `What does the ${x} say?`, + ); + problem1Version = titleOptions.indexOf(text); + expect(problem1Version).not.eq(-1); + }); - // modifyIndirectly attribute is copied (as it has propagateToProps=true) - expect(stateVariables["/frmt"].stateValues.modifyIndirectly).eq( - false, + cy.log(`select correct answer for problem 1`).then(() => { + let animal = animalOptions[problem1Version]; + let sound = soundOptions[problem1Version]; + cy.get(cesc2("#/problem12/problem1/_choiceinput1")) + .contains(sound) + .click({ force: true }); + cy.get(cesc2("#/problem12/problem1/_choiceinput1_submit")).click(); + cy.get(cesc2("#/problem12/problem1/_choiceinput1_correct")).should( + "be.visible", ); - // hide attribute is not copied (default behavior) - expect(stateVariables["/frmt"].stateValues.hidden).eq(false); - expect(stateVariables["/frmt"].stateValues.value).eq("text"); - - expect(stateVariables["/frmt2"].stateValues.modifyIndirectly).eq( - false, + cy.get( + cesc2("#/problem12/problem1/_choiceinput1_incorrect"), + ).should("not.exist"); + cy.get(cesc2("#/problem12/problem1/_feedback1")).should( + "have.text", + `That's right, the ${animal} goes ${sound}!`, ); - expect(stateVariables["/frmt2"].stateValues.hidden).eq(true); - expect(stateVariables["/frmt2"].stateValues.value).eq("text"); - - // all attributes copied when don't use prop - expect(stateVariables["/frmt3"].stateValues.modifyIndirectly).eq( - false, + cy.get(cesc2("#/problem12/problem1/_feedback2")).should( + "not.exist", ); - expect(stateVariables["/frmt3"].stateValues.value).eq("text"); - expect(stateVariables["/frmt3"].stateValues.hidden).eq(true); + }); - expect(stateVariables["/A"].stateValues.label).eq("A"); - expect(stateVariables["/cA"].stateValues.value).eqls([ - "vector", - 1, - 2, - ]); - expect(stateVariables["/l"].stateValues.value).eq( - "\\left( 1, 2 \\right)", - ); - expect(stateVariables["/l"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/lmr"].stateValues.value).eq( - "\\left( 1, 2 \\right)", - ); - expect(stateVariables["/lmr"].stateValues.modifyIndirectly).eq( - false, + cy.log(`select incorrect answer for problem 1`).then(() => { + let incorrectInd = (problem1Version + 1) % 4; + let sound = soundOptions[incorrectInd]; + cy.get(cesc2("#/problem12/problem1/_choiceinput1")) + .contains(sound) + .click({ force: true }); + cy.get(cesc2("#/problem12/problem1/_choiceinput1_submit")).click(); + cy.get(cesc2("#/problem12/problem1/_choiceinput1_correct")).should( + "not.exist", ); - expect(stateVariables["/A2"].stateValues.label).eq("A"); - expect(stateVariables["/cA2"].stateValues.value).eqls([ - "vector", - 1, - 2, - ]); - expect(stateVariables["/l2"].stateValues.value).eq( - "\\left( 1, 2 \\right)", + cy.get( + cesc2("#/problem12/problem1/_choiceinput1_incorrect"), + ).should("be.visible"); + cy.get(cesc2("#/problem12/problem1/_feedback1")).should( + "not.exist", ); - }); - }); - - it("copy props, with copySource, dot notation", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x - - - - - - - - (1,2) - - - - - - - `, - }, - "*", + cy.get(cesc2("#/problem12/problem1/_feedback2")).should( + "have.text", + `Try again.`, ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded + cy.get(cesc2("#/problem12/problem2/_title1")).should( + "have.text", + "Derivative problem", + ); - cy.log(`check properties`); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/x"].stateValues.modifyIndirectly).eq(false); - expect(stateVariables["/x"].stateValues.hidden).eq(true); - // modifyIndirectly attribute is copied (as it has propagateToProps=true) - expect(stateVariables["/mr"].stateValues.modifyIndirectly).eq( - false, + let mathinputName = + stateVariables["/problem12/problem2/_answer1"].stateValues + .inputChildren[0].componentName; + let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; + let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); + let mathinputCorrectAnchor = cesc2( + "#" + mathinputName + "_correct", ); - // hide attribute is not copied (default behavior) - expect(stateVariables["/mr"].stateValues.hidden).eq(false); - expect(stateVariables["/mr"].stateValues.value).eq(false); - - // modifyIndirectly is overwritten - expect(stateVariables["/mr2"].stateValues.modifyIndirectly).eq( - true, + let mathinputIncorrectAnchor = cesc2( + "#" + mathinputName + "_incorrect", ); - expect(stateVariables["/mr2"].stateValues.hidden).eq(false); - expect(stateVariables["/mr2"].stateValues.value).eq(false); - // modifyIndirectly attribute is copied (as it has propagateToProps=true) - expect(stateVariables["/frmt"].stateValues.modifyIndirectly).eq( - false, - ); - // hide attribute is not copied (default behavior) - expect(stateVariables["/frmt"].stateValues.hidden).eq(false); - expect(stateVariables["/frmt"].stateValues.value).eq("text"); + cy.log(`enter incorrect answer for problem 2`); + cy.get(mathinputAnchor).type("2y{enter}", { force: true }); + cy.get(mathinputSubmitAnchor).should("not.exist"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("be.visible"); - expect(stateVariables["/frmt2"].stateValues.modifyIndirectly).eq( - false, - ); - expect(stateVariables["/frmt2"].stateValues.hidden).eq(true); - expect(stateVariables["/frmt2"].stateValues.value).eq("text"); + cy.log(`enter correct answer for problem 2`); + cy.get(mathinputAnchor).type("{end}{backspace}x", { force: true }); + cy.get(mathinputSubmitAnchor).should("be.visible"); + cy.get(mathinputAnchor).type("{enter}", { force: true }); + cy.get(mathinputSubmitAnchor).should("not.exist"); + cy.get(mathinputCorrectAnchor).should("be.visible"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); + }); - // all attributes copied when don't use prop - expect(stateVariables["/frmt3"].stateValues.modifyIndirectly).eq( - false, - ); - expect(stateVariables["/frmt3"].stateValues.value).eq("text"); - expect(stateVariables["/frmt3"].stateValues.hidden).eq(true); + cy.get(cesc2("#/problem34/problem1/_p1")) + .invoke("text") + .then((text) => { + let titleOptions = animalOptions.map( + (x) => `What does the ${x} say?`, + ); + problem1Version = titleOptions.indexOf(text); + expect(problem1Version).not.eq(-1); + }); - expect(stateVariables["/A"].stateValues.label).eq("A"); - expect(stateVariables["/cA"].stateValues.value).eqls([ - "vector", - 1, - 2, - ]); - expect(stateVariables["/l"].stateValues.value).eq( - "\\left( 1, 2 \\right)", - ); - expect(stateVariables["/l"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/lmr"].stateValues.value).eq( - "\\left( 1, 2 \\right)", + cy.log(`select correct answer for problem 1`).then(() => { + let animal = animalOptions[problem1Version]; + let sound = soundOptions[problem1Version]; + cy.get(cesc2("#/problem34/problem1/_choiceinput1")) + .contains(sound) + .click({ force: true }); + cy.get(cesc2("#/problem34/problem1/_choiceinput1_submit")).click(); + cy.get(cesc2("#/problem34/problem1/_choiceinput1_correct")).should( + "be.visible", ); - expect(stateVariables["/lmr"].stateValues.modifyIndirectly).eq( - false, + cy.get( + cesc2("#/problem34/problem1/_choiceinput1_incorrect"), + ).should("not.exist"); + cy.get(cesc2("#/problem34/problem1/_feedback1")).should( + "have.text", + `That's right, the ${animal} goes ${sound}!`, ); - expect(stateVariables["/A2"].stateValues.label).eq("A"); - expect(stateVariables["/cA2"].stateValues.value).eqls([ - "vector", - 1, - 2, - ]); - expect(stateVariables["/l2"].stateValues.value).eq( - "\\left( 1, 2 \\right)", + cy.get(cesc2("#/problem34/problem1/_feedback2")).should( + "not.exist", ); }); - }); - it("copy props of copy still updatable", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (1,2) - - - - - - (, - ) - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log(`initial position`); - cy.get(cesc("#\\/p1a")).should("contain.text", "(1,2)"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p1"].stateValues.xs[0]).eq(1); - expect(stateVariables["/p1"].stateValues.xs[1]).eq(2); - expect(stateVariables["/p2"].stateValues.xs[0]).eq(1); - expect(stateVariables["/p2"].stateValues.xs[1]).eq(2); - expect(stateVariables["/p3"].stateValues.xs[0]).eq(2); - expect(stateVariables["/p3"].stateValues.xs[1]).eq(1); - }); - - cy.log(`move point 1`); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/p1", - args: { x: -3, y: 5 }, - }); - }); - - cy.get(cesc("#\\/p1a")).should("contain.text", "(−3,5)"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p1"].stateValues.xs[0]).eq(-3); - expect(stateVariables["/p1"].stateValues.xs[1]).eq(5); - expect(stateVariables["/p2"].stateValues.xs[0]).eq(-3); - expect(stateVariables["/p2"].stateValues.xs[1]).eq(5); - expect(stateVariables["/p3"].stateValues.xs[0]).eq(5); - expect(stateVariables["/p3"].stateValues.xs[1]).eq(-3); - }); - - cy.log(`move point 2`); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/p2", - args: { x: 6, y: -9 }, - }); - }); - - cy.get(cesc("#\\/p2a")).should("contain.text", "(6,−9)"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p1"].stateValues.xs[0]).eq(6); - expect(stateVariables["/p1"].stateValues.xs[1]).eq(-9); - expect(stateVariables["/p2"].stateValues.xs[0]).eq(6); - expect(stateVariables["/p2"].stateValues.xs[1]).eq(-9); - expect(stateVariables["/p3"].stateValues.xs[0]).eq(-9); - expect(stateVariables["/p3"].stateValues.xs[1]).eq(6); - }); - - cy.log(`move point 3`); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/p3", - args: { x: -1, y: -7 }, - }); - }); - - cy.get(cesc("#\\/p3a")).should("contain.text", "(−1,−7)"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p1"].stateValues.xs[0]).eq(-7); - expect(stateVariables["/p1"].stateValues.xs[1]).eq(-1); - expect(stateVariables["/p2"].stateValues.xs[0]).eq(-7); - expect(stateVariables["/p2"].stateValues.xs[1]).eq(-1); - expect(stateVariables["/p3"].stateValues.xs[0]).eq(-1); - expect(stateVariables["/p3"].stateValues.xs[1]).eq(-7); - }); - }); - - it("copy props of copy still updatable, dot notation", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (1,2) - - - - - - (, - ) - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log(`initial position`); - cy.get(cesc("#\\/p1a")).should("contain.text", "(1,2)"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p1"].stateValues.xs[0]).eq(1); - expect(stateVariables["/p1"].stateValues.xs[1]).eq(2); - expect(stateVariables["/p2"].stateValues.xs[0]).eq(1); - expect(stateVariables["/p2"].stateValues.xs[1]).eq(2); - expect(stateVariables["/p3"].stateValues.xs[0]).eq(2); - expect(stateVariables["/p3"].stateValues.xs[1]).eq(1); - }); - - cy.log(`move point 1`); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/p1", - args: { x: -3, y: 5 }, - }); - }); - - cy.get(cesc("#\\/p1a")).should("contain.text", "(−3,5)"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p1"].stateValues.xs[0]).eq(-3); - expect(stateVariables["/p1"].stateValues.xs[1]).eq(5); - expect(stateVariables["/p2"].stateValues.xs[0]).eq(-3); - expect(stateVariables["/p2"].stateValues.xs[1]).eq(5); - expect(stateVariables["/p3"].stateValues.xs[0]).eq(5); - expect(stateVariables["/p3"].stateValues.xs[1]).eq(-3); - }); - - cy.log(`move point 2`); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/p2", - args: { x: 6, y: -9 }, - }); - }); - - cy.get(cesc("#\\/p2a")).should("contain.text", "(6,−9)"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p1"].stateValues.xs[0]).eq(6); - expect(stateVariables["/p1"].stateValues.xs[1]).eq(-9); - expect(stateVariables["/p2"].stateValues.xs[0]).eq(6); - expect(stateVariables["/p2"].stateValues.xs[1]).eq(-9); - expect(stateVariables["/p3"].stateValues.xs[0]).eq(-9); - expect(stateVariables["/p3"].stateValues.xs[1]).eq(6); - }); - - cy.log(`move point 3`); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/p3", - args: { x: -1, y: -7 }, - }); - }); - - cy.get(cesc("#\\/p3a")).should("contain.text", "(−1,−7)"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p1"].stateValues.xs[0]).eq(-7); - expect(stateVariables["/p1"].stateValues.xs[1]).eq(-1); - expect(stateVariables["/p2"].stateValues.xs[0]).eq(-7); - expect(stateVariables["/p2"].stateValues.xs[1]).eq(-1); - expect(stateVariables["/p3"].stateValues.xs[0]).eq(-1); - expect(stateVariables["/p3"].stateValues.xs[1]).eq(-7); - }); - }); - - it("copy props of copy still updatable, dot notation, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (1,2) - - - - $p1{name="p2"} - - ($p2.y, $p2.x1) - - - $p1{name="p1a"} - $p2{name="p2a"} - $p3{name="p3a"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log(`initial position`); - cy.get(cesc("#\\/p1a")).should("contain.text", "(1,2)"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p1"].stateValues.xs[0]).eq(1); - expect(stateVariables["/p1"].stateValues.xs[1]).eq(2); - expect(stateVariables["/p2"].stateValues.xs[0]).eq(1); - expect(stateVariables["/p2"].stateValues.xs[1]).eq(2); - expect(stateVariables["/p3"].stateValues.xs[0]).eq(2); - expect(stateVariables["/p3"].stateValues.xs[1]).eq(1); - }); - - cy.log(`move point 1`); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/p1", - args: { x: -3, y: 5 }, - }); - }); - - cy.get(cesc("#\\/p1a")).should("contain.text", "(−3,5)"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p1"].stateValues.xs[0]).eq(-3); - expect(stateVariables["/p1"].stateValues.xs[1]).eq(5); - expect(stateVariables["/p2"].stateValues.xs[0]).eq(-3); - expect(stateVariables["/p2"].stateValues.xs[1]).eq(5); - expect(stateVariables["/p3"].stateValues.xs[0]).eq(5); - expect(stateVariables["/p3"].stateValues.xs[1]).eq(-3); - }); - - cy.log(`move point 2`); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/p2", - args: { x: 6, y: -9 }, - }); - }); - - cy.get(cesc("#\\/p2a")).should("contain.text", "(6,−9)"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p1"].stateValues.xs[0]).eq(6); - expect(stateVariables["/p1"].stateValues.xs[1]).eq(-9); - expect(stateVariables["/p2"].stateValues.xs[0]).eq(6); - expect(stateVariables["/p2"].stateValues.xs[1]).eq(-9); - expect(stateVariables["/p3"].stateValues.xs[0]).eq(-9); - expect(stateVariables["/p3"].stateValues.xs[1]).eq(6); - }); - - cy.log(`move point 3`); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/p3", - args: { x: -1, y: -7 }, - }); - }); - - cy.get(cesc("#\\/p3a")).should("contain.text", "(−1,−7)"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p1"].stateValues.xs[0]).eq(-7); - expect(stateVariables["/p1"].stateValues.xs[1]).eq(-1); - expect(stateVariables["/p2"].stateValues.xs[0]).eq(-7); - expect(stateVariables["/p2"].stateValues.xs[1]).eq(-1); - expect(stateVariables["/p3"].stateValues.xs[0]).eq(-1); - expect(stateVariables["/p3"].stateValues.xs[1]).eq(-7); - }); - }); - - it("copy props of copy still updatable, with copySource", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (1,2) - - - - - - (, - ) - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log(`initial position`); - cy.get(cesc("#\\/p1a")).should("contain.text", "(1,2)"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p1"].stateValues.xs[0]).eq(1); - expect(stateVariables["/p1"].stateValues.xs[1]).eq(2); - expect(stateVariables["/p2"].stateValues.xs[0]).eq(1); - expect(stateVariables["/p2"].stateValues.xs[1]).eq(2); - expect(stateVariables["/p3"].stateValues.xs[0]).eq(2); - expect(stateVariables["/p3"].stateValues.xs[1]).eq(1); - }); - - cy.log(`move point 1`); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/p1", - args: { x: -3, y: 5 }, - }); - }); - - cy.get(cesc("#\\/p1a")).should("contain.text", "(−3,5)"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p1"].stateValues.xs[0]).eq(-3); - expect(stateVariables["/p1"].stateValues.xs[1]).eq(5); - expect(stateVariables["/p2"].stateValues.xs[0]).eq(-3); - expect(stateVariables["/p2"].stateValues.xs[1]).eq(5); - expect(stateVariables["/p3"].stateValues.xs[0]).eq(5); - expect(stateVariables["/p3"].stateValues.xs[1]).eq(-3); - }); - - cy.log(`move point 2`); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/p2", - args: { x: 6, y: -9 }, - }); - }); - - cy.get(cesc("#\\/p2a")).should("contain.text", "(6,−9)"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p1"].stateValues.xs[0]).eq(6); - expect(stateVariables["/p1"].stateValues.xs[1]).eq(-9); - expect(stateVariables["/p2"].stateValues.xs[0]).eq(6); - expect(stateVariables["/p2"].stateValues.xs[1]).eq(-9); - expect(stateVariables["/p3"].stateValues.xs[0]).eq(-9); - expect(stateVariables["/p3"].stateValues.xs[1]).eq(6); - }); - - cy.log(`move point 3`); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/p3", - args: { x: -1, y: -7 }, - }); - }); - - cy.get(cesc("#\\/p3a")).should("contain.text", "(−1,−7)"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p1"].stateValues.xs[0]).eq(-7); - expect(stateVariables["/p1"].stateValues.xs[1]).eq(-1); - expect(stateVariables["/p2"].stateValues.xs[0]).eq(-7); - expect(stateVariables["/p2"].stateValues.xs[1]).eq(-1); - expect(stateVariables["/p3"].stateValues.xs[0]).eq(-1); - expect(stateVariables["/p3"].stateValues.xs[1]).eq(-7); - }); - }); - - it("copy props of copy still updatable, with copySource, dot notation", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (1,2) - - - - - - (, - ) - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log(`initial position`); - cy.get(cesc("#\\/p1a")).should("contain.text", "(1,2)"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p1"].stateValues.xs[0]).eq(1); - expect(stateVariables["/p1"].stateValues.xs[1]).eq(2); - expect(stateVariables["/p2"].stateValues.xs[0]).eq(1); - expect(stateVariables["/p2"].stateValues.xs[1]).eq(2); - expect(stateVariables["/p3"].stateValues.xs[0]).eq(2); - expect(stateVariables["/p3"].stateValues.xs[1]).eq(1); - }); - - cy.log(`move point 1`); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/p1", - args: { x: -3, y: 5 }, - }); - }); - - cy.get(cesc("#\\/p1a")).should("contain.text", "(−3,5)"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p1"].stateValues.xs[0]).eq(-3); - expect(stateVariables["/p1"].stateValues.xs[1]).eq(5); - expect(stateVariables["/p2"].stateValues.xs[0]).eq(-3); - expect(stateVariables["/p2"].stateValues.xs[1]).eq(5); - expect(stateVariables["/p3"].stateValues.xs[0]).eq(5); - expect(stateVariables["/p3"].stateValues.xs[1]).eq(-3); - }); - - cy.log(`move point 2`); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/p2", - args: { x: 6, y: -9 }, - }); - }); - - cy.get(cesc("#\\/p2a")).should("contain.text", "(6,−9)"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p1"].stateValues.xs[0]).eq(6); - expect(stateVariables["/p1"].stateValues.xs[1]).eq(-9); - expect(stateVariables["/p2"].stateValues.xs[0]).eq(6); - expect(stateVariables["/p2"].stateValues.xs[1]).eq(-9); - expect(stateVariables["/p3"].stateValues.xs[0]).eq(-9); - expect(stateVariables["/p3"].stateValues.xs[1]).eq(6); - }); - - cy.log(`move point 3`); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/p3", - args: { x: -1, y: -7 }, - }); - }); - - cy.get(cesc("#\\/p3a")).should("contain.text", "(−1,−7)"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p1"].stateValues.xs[0]).eq(-7); - expect(stateVariables["/p1"].stateValues.xs[1]).eq(-1); - expect(stateVariables["/p2"].stateValues.xs[0]).eq(-7); - expect(stateVariables["/p2"].stateValues.xs[1]).eq(-1); - expect(stateVariables["/p3"].stateValues.xs[0]).eq(-1); - expect(stateVariables["/p3"].stateValues.xs[1]).eq(-7); - }); - }); - - it.skip("copy invalid prop", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - x - - - - - - - - - - - - `, - }, - "*", - ); - }); - - cy.get("#__math1"); //wait for page to load - - // How to check if the right errors get thrown for these? - }); - - it("copy of prop copy shadows source", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log(`initial positions`); - cy.window().then(async (win) => { - let displacement = [-4, 2]; - let v_tail = [1, 1]; - let d_tail = [0, 0]; - let v_head = displacement.map((x, i) => x + v_tail[i]); - let d_head = displacement.map((x, i) => x + d_tail[i]); - - cy.get(cesc("#\\/v1a")).should( - "contain.text", - `(${nInDOM(displacement[0])},${nInDOM(displacement[1])})`, - ); - - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_vector1"].stateValues.tail).eqls([ - ...v_tail, - ]); - expect(stateVariables["/_vector1"].stateValues.head).eqls([ - ...v_head, - ]); - expect(stateVariables["/_vector1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d1"].stateValues.tail).eqls([...d_tail]); - expect(stateVariables["/d1"].stateValues.head).eqls([...d_head]); - expect(stateVariables["/d1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d2"].stateValues.tail).eqls([...d_tail]); - expect(stateVariables["/d2"].stateValues.head).eqls([...d_head]); - expect(stateVariables["/d2"].stateValues.displacement).eqls([ - ...displacement, - ]); - }); - - cy.log(`move vector 1`); - cy.window().then(async (win) => { - let displacement = [3, 1]; - let v_tail = [-1, 4]; - let d_tail = [0, 0]; - let v_head = displacement.map((x, i) => x + v_tail[i]); - let d_head = displacement.map((x, i) => x + d_tail[i]); - - win.callAction1({ - actionName: "moveVector", - componentName: "/_vector1", - args: { - tailcoords: v_tail, - headcoords: v_head, - }, - }); - - cy.get(cesc("#\\/v1a")).should( - "contain.text", - `(${nInDOM(displacement[0])},${nInDOM(displacement[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_vector1"].stateValues.tail).eqls([ - ...v_tail, - ]); - expect(stateVariables["/_vector1"].stateValues.head).eqls([ - ...v_head, - ]); - expect( - stateVariables["/_vector1"].stateValues.displacement, - ).eqls([...displacement]); - expect(stateVariables["/d1"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d1"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d2"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d2"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d2"].stateValues.displacement).eqls([ - ...displacement, - ]); - }); - }); - - cy.log(`move vector 2`); - cy.window().then(async (win) => { - let displacement = [5, -2]; - let v_tail = [-1, 4]; - let d_tail = [3, -7]; - let v_head = displacement.map((x, i) => x + v_tail[i]); - let d_head = displacement.map((x, i) => x + d_tail[i]); - - win.callAction1({ - actionName: "moveVector", - componentName: "/d1", - args: { - tailcoords: d_tail, - headcoords: d_head, - }, - }); - - cy.get(cesc("#\\/v1a")).should( - "contain.text", - `(${nInDOM(displacement[0])},${nInDOM(displacement[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_vector1"].stateValues.tail).eqls([ - ...v_tail, - ]); - expect(stateVariables["/_vector1"].stateValues.head).eqls([ - ...v_head, - ]); - expect( - stateVariables["/_vector1"].stateValues.displacement, - ).eqls([...displacement]); - expect(stateVariables["/d1"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d1"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d2"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d2"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d2"].stateValues.displacement).eqls([ - ...displacement, - ]); - }); - }); - - cy.log(`move vector 3`); - cy.window().then(async (win) => { - let displacement = [-3, 6]; - let v_tail = [-1, 4]; - let d_tail = [4, -2]; - let v_head = displacement.map((x, i) => x + v_tail[i]); - let d_head = displacement.map((x, i) => x + d_tail[i]); - - win.callAction1({ - actionName: "moveVector", - componentName: "/d2", - args: { - tailcoords: d_tail, - headcoords: d_head, - }, - }); - - cy.get(cesc("#\\/v1a")).should( - "contain.text", - `(${nInDOM(displacement[0])},${nInDOM(displacement[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_vector1"].stateValues.tail).eqls([ - ...v_tail, - ]); - expect(stateVariables["/_vector1"].stateValues.head).eqls([ - ...v_head, - ]); - expect( - stateVariables["/_vector1"].stateValues.displacement, - ).eqls([...displacement]); - expect(stateVariables["/d1"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d1"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d2"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d2"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d2"].stateValues.displacement).eqls([ - ...displacement, - ]); - }); - }); - - cy.log(`move vector 1`); - cy.window().then(async (win) => { - let displacement = [5, 0]; - let v_tail = [-8, 6]; - let d_tail = [4, -2]; - let v_head = displacement.map((x, i) => x + v_tail[i]); - let d_head = displacement.map((x, i) => x + d_tail[i]); - - win.callAction1({ - actionName: "moveVector", - componentName: "/_vector1", - args: { - tailcoords: v_tail, - headcoords: v_head, - }, - }); - - cy.get(cesc("#\\/v1a")).should( - "contain.text", - `(${nInDOM(displacement[0])},${nInDOM(displacement[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_vector1"].stateValues.tail).eqls([ - ...v_tail, - ]); - expect(stateVariables["/_vector1"].stateValues.head).eqls([ - ...v_head, - ]); - expect( - stateVariables["/_vector1"].stateValues.displacement, - ).eqls([...displacement]); - expect(stateVariables["/d1"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d1"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d2"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d2"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d2"].stateValues.displacement).eqls([ - ...displacement, - ]); - }); - }); - }); - - it("copy of prop copy shadows source, dot notation", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log(`initial positions`); - cy.window().then(async (win) => { - let displacement = [-4, 2]; - let v_tail = [1, 1]; - let d_tail = [0, 0]; - let v_head = displacement.map((x, i) => x + v_tail[i]); - let d_head = displacement.map((x, i) => x + d_tail[i]); - - cy.get(cesc("#\\/v1a")).should( - "contain.text", - `(${nInDOM(displacement[0])},${nInDOM(displacement[1])})`, - ); - - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_vector1"].stateValues.tail).eqls([ - ...v_tail, - ]); - expect(stateVariables["/_vector1"].stateValues.head).eqls([ - ...v_head, - ]); - expect(stateVariables["/_vector1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d1"].stateValues.tail).eqls([...d_tail]); - expect(stateVariables["/d1"].stateValues.head).eqls([...d_head]); - expect(stateVariables["/d1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d2"].stateValues.tail).eqls([...d_tail]); - expect(stateVariables["/d2"].stateValues.head).eqls([...d_head]); - expect(stateVariables["/d2"].stateValues.displacement).eqls([ - ...displacement, - ]); - }); - - cy.log(`move vector 1`); - cy.window().then(async (win) => { - let displacement = [3, 1]; - let v_tail = [-1, 4]; - let d_tail = [0, 0]; - let v_head = displacement.map((x, i) => x + v_tail[i]); - let d_head = displacement.map((x, i) => x + d_tail[i]); - - win.callAction1({ - actionName: "moveVector", - componentName: "/_vector1", - args: { - tailcoords: v_tail, - headcoords: v_head, - }, - }); - - cy.get(cesc("#\\/v1a")).should( - "contain.text", - `(${nInDOM(displacement[0])},${nInDOM(displacement[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_vector1"].stateValues.tail).eqls([ - ...v_tail, - ]); - expect(stateVariables["/_vector1"].stateValues.head).eqls([ - ...v_head, - ]); - expect( - stateVariables["/_vector1"].stateValues.displacement, - ).eqls([...displacement]); - expect(stateVariables["/d1"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d1"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d2"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d2"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d2"].stateValues.displacement).eqls([ - ...displacement, - ]); - }); - }); - - cy.log(`move vector 2`); - cy.window().then(async (win) => { - let displacement = [5, -2]; - let v_tail = [-1, 4]; - let d_tail = [3, -7]; - let v_head = displacement.map((x, i) => x + v_tail[i]); - let d_head = displacement.map((x, i) => x + d_tail[i]); - - win.callAction1({ - actionName: "moveVector", - componentName: "/d1", - args: { - tailcoords: d_tail, - headcoords: d_head, - }, - }); - - cy.get(cesc("#\\/v1a")).should( - "contain.text", - `(${nInDOM(displacement[0])},${nInDOM(displacement[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_vector1"].stateValues.tail).eqls([ - ...v_tail, - ]); - expect(stateVariables["/_vector1"].stateValues.head).eqls([ - ...v_head, - ]); - expect( - stateVariables["/_vector1"].stateValues.displacement, - ).eqls([...displacement]); - expect(stateVariables["/d1"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d1"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d2"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d2"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d2"].stateValues.displacement).eqls([ - ...displacement, - ]); - }); - }); - - cy.log(`move vector 3`); - cy.window().then(async (win) => { - let displacement = [-3, 6]; - let v_tail = [-1, 4]; - let d_tail = [4, -2]; - let v_head = displacement.map((x, i) => x + v_tail[i]); - let d_head = displacement.map((x, i) => x + d_tail[i]); - - win.callAction1({ - actionName: "moveVector", - componentName: "/d2", - args: { - tailcoords: d_tail, - headcoords: d_head, - }, - }); - - cy.get(cesc("#\\/v1a")).should( - "contain.text", - `(${nInDOM(displacement[0])},${nInDOM(displacement[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_vector1"].stateValues.tail).eqls([ - ...v_tail, - ]); - expect(stateVariables["/_vector1"].stateValues.head).eqls([ - ...v_head, - ]); - expect( - stateVariables["/_vector1"].stateValues.displacement, - ).eqls([...displacement]); - expect(stateVariables["/d1"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d1"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d2"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d2"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d2"].stateValues.displacement).eqls([ - ...displacement, - ]); - }); - }); - - cy.log(`move vector 1`); - cy.window().then(async (win) => { - let displacement = [5, 0]; - let v_tail = [-8, 6]; - let d_tail = [4, -2]; - let v_head = displacement.map((x, i) => x + v_tail[i]); - let d_head = displacement.map((x, i) => x + d_tail[i]); - - win.callAction1({ - actionName: "moveVector", - componentName: "/_vector1", - args: { - tailcoords: v_tail, - headcoords: v_head, - }, - }); - - cy.get(cesc("#\\/v1a")).should( - "contain.text", - `(${nInDOM(displacement[0])},${nInDOM(displacement[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_vector1"].stateValues.tail).eqls([ - ...v_tail, - ]); - expect(stateVariables["/_vector1"].stateValues.head).eqls([ - ...v_head, - ]); - expect( - stateVariables["/_vector1"].stateValues.displacement, - ).eqls([...displacement]); - expect(stateVariables["/d1"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d1"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d2"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d2"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d2"].stateValues.displacement).eqls([ - ...displacement, - ]); - }); - }); - }); - - it("copy of prop copy shadows source, dot notation, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - $(_vector1.displacement{assignNames="d1"}) - - - - $d1{name="d2"} - - - $_vector1{name="v1a"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log(`initial positions`); - cy.window().then(async (win) => { - let displacement = [-4, 2]; - let v_tail = [1, 1]; - let d_tail = [0, 0]; - let v_head = displacement.map((x, i) => x + v_tail[i]); - let d_head = displacement.map((x, i) => x + d_tail[i]); - - cy.get(cesc("#\\/v1a")).should( - "contain.text", - `(${nInDOM(displacement[0])},${nInDOM(displacement[1])})`, - ); - - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_vector1"].stateValues.tail).eqls([ - ...v_tail, - ]); - expect(stateVariables["/_vector1"].stateValues.head).eqls([ - ...v_head, - ]); - expect(stateVariables["/_vector1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d1"].stateValues.tail).eqls([...d_tail]); - expect(stateVariables["/d1"].stateValues.head).eqls([...d_head]); - expect(stateVariables["/d1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d2"].stateValues.tail).eqls([...d_tail]); - expect(stateVariables["/d2"].stateValues.head).eqls([...d_head]); - expect(stateVariables["/d2"].stateValues.displacement).eqls([ - ...displacement, - ]); - }); - - cy.log(`move vector 1`); - cy.window().then(async (win) => { - let displacement = [3, 1]; - let v_tail = [-1, 4]; - let d_tail = [0, 0]; - let v_head = displacement.map((x, i) => x + v_tail[i]); - let d_head = displacement.map((x, i) => x + d_tail[i]); - - win.callAction1({ - actionName: "moveVector", - componentName: "/_vector1", - args: { - tailcoords: v_tail, - headcoords: v_head, - }, - }); - - cy.get(cesc("#\\/v1a")).should( - "contain.text", - `(${nInDOM(displacement[0])},${nInDOM(displacement[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_vector1"].stateValues.tail).eqls([ - ...v_tail, - ]); - expect(stateVariables["/_vector1"].stateValues.head).eqls([ - ...v_head, - ]); - expect( - stateVariables["/_vector1"].stateValues.displacement, - ).eqls([...displacement]); - expect(stateVariables["/d1"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d1"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d2"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d2"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d2"].stateValues.displacement).eqls([ - ...displacement, - ]); - }); - }); - - cy.log(`move vector 2`); - cy.window().then(async (win) => { - let displacement = [5, -2]; - let v_tail = [-1, 4]; - let d_tail = [3, -7]; - let v_head = displacement.map((x, i) => x + v_tail[i]); - let d_head = displacement.map((x, i) => x + d_tail[i]); - - win.callAction1({ - actionName: "moveVector", - componentName: "/d1", - args: { - tailcoords: d_tail, - headcoords: d_head, - }, - }); - - cy.get(cesc("#\\/v1a")).should( - "contain.text", - `(${nInDOM(displacement[0])},${nInDOM(displacement[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_vector1"].stateValues.tail).eqls([ - ...v_tail, - ]); - expect(stateVariables["/_vector1"].stateValues.head).eqls([ - ...v_head, - ]); - expect( - stateVariables["/_vector1"].stateValues.displacement, - ).eqls([...displacement]); - expect(stateVariables["/d1"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d1"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d2"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d2"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d2"].stateValues.displacement).eqls([ - ...displacement, - ]); - }); - }); - - cy.log(`move vector 3`); - cy.window().then(async (win) => { - let displacement = [-3, 6]; - let v_tail = [-1, 4]; - let d_tail = [4, -2]; - let v_head = displacement.map((x, i) => x + v_tail[i]); - let d_head = displacement.map((x, i) => x + d_tail[i]); - - win.callAction1({ - actionName: "moveVector", - componentName: "/d2", - args: { - tailcoords: d_tail, - headcoords: d_head, - }, - }); - - cy.get(cesc("#\\/v1a")).should( - "contain.text", - `(${nInDOM(displacement[0])},${nInDOM(displacement[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_vector1"].stateValues.tail).eqls([ - ...v_tail, - ]); - expect(stateVariables["/_vector1"].stateValues.head).eqls([ - ...v_head, - ]); - expect( - stateVariables["/_vector1"].stateValues.displacement, - ).eqls([...displacement]); - expect(stateVariables["/d1"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d1"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d2"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d2"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d2"].stateValues.displacement).eqls([ - ...displacement, - ]); - }); - }); - - cy.log(`move vector 1`); - cy.window().then(async (win) => { - let displacement = [5, 0]; - let v_tail = [-8, 6]; - let d_tail = [4, -2]; - let v_head = displacement.map((x, i) => x + v_tail[i]); - let d_head = displacement.map((x, i) => x + d_tail[i]); - - win.callAction1({ - actionName: "moveVector", - componentName: "/_vector1", - args: { - tailcoords: v_tail, - headcoords: v_head, - }, - }); - - cy.get(cesc("#\\/v1a")).should( - "contain.text", - `(${nInDOM(displacement[0])},${nInDOM(displacement[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_vector1"].stateValues.tail).eqls([ - ...v_tail, - ]); - expect(stateVariables["/_vector1"].stateValues.head).eqls([ - ...v_head, - ]); - expect( - stateVariables["/_vector1"].stateValues.displacement, - ).eqls([...displacement]); - expect(stateVariables["/d1"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d1"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d2"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d2"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d2"].stateValues.displacement).eqls([ - ...displacement, - ]); - }); - }); - }); - - it("copy of prop copy shadows source, with copySource", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log(`initial positions`); - cy.window().then(async (win) => { - let displacement = [-4, 2]; - let v_tail = [1, 1]; - let d_tail = [0, 0]; - let v_head = displacement.map((x, i) => x + v_tail[i]); - let d_head = displacement.map((x, i) => x + d_tail[i]); - - cy.get(cesc("#\\/v1a")).should( - "contain.text", - `(${nInDOM(displacement[0])},${nInDOM(displacement[1])})`, - ); - - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_vector1"].stateValues.tail).eqls([ - ...v_tail, - ]); - expect(stateVariables["/_vector1"].stateValues.head).eqls([ - ...v_head, - ]); - expect(stateVariables["/_vector1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d1"].stateValues.tail).eqls([...d_tail]); - expect(stateVariables["/d1"].stateValues.head).eqls([...d_head]); - expect(stateVariables["/d1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d2"].stateValues.tail).eqls([...d_tail]); - expect(stateVariables["/d2"].stateValues.head).eqls([...d_head]); - expect(stateVariables["/d2"].stateValues.displacement).eqls([ - ...displacement, - ]); - }); - - cy.log(`move vector 1`); - cy.window().then(async (win) => { - let displacement = [3, 1]; - let v_tail = [-1, 4]; - let d_tail = [0, 0]; - let v_head = displacement.map((x, i) => x + v_tail[i]); - let d_head = displacement.map((x, i) => x + d_tail[i]); - - win.callAction1({ - actionName: "moveVector", - componentName: "/_vector1", - args: { - tailcoords: v_tail, - headcoords: v_head, - }, - }); - - cy.get(cesc("#\\/v1a")).should( - "contain.text", - `(${nInDOM(displacement[0])},${nInDOM(displacement[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_vector1"].stateValues.tail).eqls([ - ...v_tail, - ]); - expect(stateVariables["/_vector1"].stateValues.head).eqls([ - ...v_head, - ]); - expect( - stateVariables["/_vector1"].stateValues.displacement, - ).eqls([...displacement]); - expect(stateVariables["/d1"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d1"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d2"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d2"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d2"].stateValues.displacement).eqls([ - ...displacement, - ]); - }); - }); - - cy.log(`move vector 2`); - cy.window().then(async (win) => { - let displacement = [5, -2]; - let v_tail = [-1, 4]; - let d_tail = [3, -7]; - let v_head = displacement.map((x, i) => x + v_tail[i]); - let d_head = displacement.map((x, i) => x + d_tail[i]); - - win.callAction1({ - actionName: "moveVector", - componentName: "/d1", - args: { - tailcoords: d_tail, - headcoords: d_head, - }, - }); - - cy.get(cesc("#\\/v1a")).should( - "contain.text", - `(${nInDOM(displacement[0])},${nInDOM(displacement[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_vector1"].stateValues.tail).eqls([ - ...v_tail, - ]); - expect(stateVariables["/_vector1"].stateValues.head).eqls([ - ...v_head, - ]); - expect( - stateVariables["/_vector1"].stateValues.displacement, - ).eqls([...displacement]); - expect(stateVariables["/d1"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d1"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d2"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d2"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d2"].stateValues.displacement).eqls([ - ...displacement, - ]); - }); - }); - - cy.log(`move vector 3`); - cy.window().then(async (win) => { - let displacement = [-3, 6]; - let v_tail = [-1, 4]; - let d_tail = [4, -2]; - let v_head = displacement.map((x, i) => x + v_tail[i]); - let d_head = displacement.map((x, i) => x + d_tail[i]); - - win.callAction1({ - actionName: "moveVector", - componentName: "/d2", - args: { - tailcoords: d_tail, - headcoords: d_head, - }, - }); - - cy.get(cesc("#\\/v1a")).should( - "contain.text", - `(${nInDOM(displacement[0])},${nInDOM(displacement[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_vector1"].stateValues.tail).eqls([ - ...v_tail, - ]); - expect(stateVariables["/_vector1"].stateValues.head).eqls([ - ...v_head, - ]); - expect( - stateVariables["/_vector1"].stateValues.displacement, - ).eqls([...displacement]); - expect(stateVariables["/d1"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d1"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d2"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d2"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d2"].stateValues.displacement).eqls([ - ...displacement, - ]); - }); - }); - - cy.log(`move vector 1`); - cy.window().then(async (win) => { - let displacement = [5, 0]; - let v_tail = [-8, 6]; - let d_tail = [4, -2]; - let v_head = displacement.map((x, i) => x + v_tail[i]); - let d_head = displacement.map((x, i) => x + d_tail[i]); - - win.callAction1({ - actionName: "moveVector", - componentName: "/_vector1", - args: { - tailcoords: v_tail, - headcoords: v_head, - }, - }); - - cy.get(cesc("#\\/v1a")).should( - "contain.text", - `(${nInDOM(displacement[0])},${nInDOM(displacement[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_vector1"].stateValues.tail).eqls([ - ...v_tail, - ]); - expect(stateVariables["/_vector1"].stateValues.head).eqls([ - ...v_head, - ]); - expect( - stateVariables["/_vector1"].stateValues.displacement, - ).eqls([...displacement]); - expect(stateVariables["/d1"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d1"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d2"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d2"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d2"].stateValues.displacement).eqls([ - ...displacement, - ]); - }); - }); - }); - - it("copy of prop copy shadows source, with copySource, dot notation", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log(`initial positions`); - cy.window().then(async (win) => { - let displacement = [-4, 2]; - let v_tail = [1, 1]; - let d_tail = [0, 0]; - let v_head = displacement.map((x, i) => x + v_tail[i]); - let d_head = displacement.map((x, i) => x + d_tail[i]); - - cy.get(cesc("#\\/v1a")).should( - "contain.text", - `(${nInDOM(displacement[0])},${nInDOM(displacement[1])})`, - ); - - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_vector1"].stateValues.tail).eqls([ - ...v_tail, - ]); - expect(stateVariables["/_vector1"].stateValues.head).eqls([ - ...v_head, - ]); - expect(stateVariables["/_vector1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d1"].stateValues.tail).eqls([...d_tail]); - expect(stateVariables["/d1"].stateValues.head).eqls([...d_head]); - expect(stateVariables["/d1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d2"].stateValues.tail).eqls([...d_tail]); - expect(stateVariables["/d2"].stateValues.head).eqls([...d_head]); - expect(stateVariables["/d2"].stateValues.displacement).eqls([ - ...displacement, - ]); - }); - - cy.log(`move vector 1`); - cy.window().then(async (win) => { - let displacement = [3, 1]; - let v_tail = [-1, 4]; - let d_tail = [0, 0]; - let v_head = displacement.map((x, i) => x + v_tail[i]); - let d_head = displacement.map((x, i) => x + d_tail[i]); - - win.callAction1({ - actionName: "moveVector", - componentName: "/_vector1", - args: { - tailcoords: v_tail, - headcoords: v_head, - }, - }); - - cy.get(cesc("#\\/v1a")).should( - "contain.text", - `(${nInDOM(displacement[0])},${nInDOM(displacement[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_vector1"].stateValues.tail).eqls([ - ...v_tail, - ]); - expect(stateVariables["/_vector1"].stateValues.head).eqls([ - ...v_head, - ]); - expect( - stateVariables["/_vector1"].stateValues.displacement, - ).eqls([...displacement]); - expect(stateVariables["/d1"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d1"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d2"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d2"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d2"].stateValues.displacement).eqls([ - ...displacement, - ]); - }); - }); - - cy.log(`move vector 2`); - cy.window().then(async (win) => { - let displacement = [5, -2]; - let v_tail = [-1, 4]; - let d_tail = [3, -7]; - let v_head = displacement.map((x, i) => x + v_tail[i]); - let d_head = displacement.map((x, i) => x + d_tail[i]); - - win.callAction1({ - actionName: "moveVector", - componentName: "/d1", - args: { - tailcoords: d_tail, - headcoords: d_head, - }, - }); - - cy.get(cesc("#\\/v1a")).should( - "contain.text", - `(${nInDOM(displacement[0])},${nInDOM(displacement[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_vector1"].stateValues.tail).eqls([ - ...v_tail, - ]); - expect(stateVariables["/_vector1"].stateValues.head).eqls([ - ...v_head, - ]); - expect( - stateVariables["/_vector1"].stateValues.displacement, - ).eqls([...displacement]); - expect(stateVariables["/d1"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d1"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d2"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d2"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d2"].stateValues.displacement).eqls([ - ...displacement, - ]); - }); - }); - - cy.log(`move vector 3`); - cy.window().then(async (win) => { - let displacement = [-3, 6]; - let v_tail = [-1, 4]; - let d_tail = [4, -2]; - let v_head = displacement.map((x, i) => x + v_tail[i]); - let d_head = displacement.map((x, i) => x + d_tail[i]); - - win.callAction1({ - actionName: "moveVector", - componentName: "/d2", - args: { - tailcoords: d_tail, - headcoords: d_head, - }, - }); - - cy.get(cesc("#\\/v1a")).should( - "contain.text", - `(${nInDOM(displacement[0])},${nInDOM(displacement[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_vector1"].stateValues.tail).eqls([ - ...v_tail, - ]); - expect(stateVariables["/_vector1"].stateValues.head).eqls([ - ...v_head, - ]); - expect( - stateVariables["/_vector1"].stateValues.displacement, - ).eqls([...displacement]); - expect(stateVariables["/d1"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d1"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d2"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d2"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d2"].stateValues.displacement).eqls([ - ...displacement, - ]); - }); - }); - - cy.log(`move vector 1`); - cy.window().then(async (win) => { - let displacement = [5, 0]; - let v_tail = [-8, 6]; - let d_tail = [4, -2]; - let v_head = displacement.map((x, i) => x + v_tail[i]); - let d_head = displacement.map((x, i) => x + d_tail[i]); - - win.callAction1({ - actionName: "moveVector", - componentName: "/_vector1", - args: { - tailcoords: v_tail, - headcoords: v_head, - }, - }); - - cy.get(cesc("#\\/v1a")).should( - "contain.text", - `(${nInDOM(displacement[0])},${nInDOM(displacement[1])})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_vector1"].stateValues.tail).eqls([ - ...v_tail, - ]); - expect(stateVariables["/_vector1"].stateValues.head).eqls([ - ...v_head, - ]); - expect( - stateVariables["/_vector1"].stateValues.displacement, - ).eqls([...displacement]); - expect(stateVariables["/d1"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d1"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d1"].stateValues.displacement).eqls([ - ...displacement, - ]); - expect(stateVariables["/d2"].stateValues.tail).eqls([ - ...d_tail, - ]); - expect(stateVariables["/d2"].stateValues.head).eqls([ - ...d_head, - ]); - expect(stateVariables["/d2"].stateValues.displacement).eqls([ - ...displacement, - ]); - }); - }); - }); - - it("property children account for replacement changes", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

- - - -

- -

- - -

- - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/_p1")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - cy.get(cesc("#\\/_p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - cy.get(cesc("#\\/p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - cy.get(cesc("#\\/_p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - cy.get(cesc("#\\/p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type("2{enter}", { - force: true, - }); - - cy.get(cesc("#\\/_p1")).should("contain.text", "a, b"); - - cy.get(cesc("#\\/_p1")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b"); - }); - cy.get(cesc("#\\/_p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b"); - }); - cy.get(cesc("#\\/p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b"); - }); - cy.get(cesc("#\\/_p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b"); - }); - cy.get(cesc("#\\/p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b"); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{end}{backspace}5{enter}", - { force: true }, - ); - cy.get(cesc("#\\/_p1")).should("contain.text", "a, b, c, d, e"); - cy.get(cesc("#\\/_p1")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e"); - }); - cy.get(cesc("#\\/_p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e"); - }); - cy.get(cesc("#\\/p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e"); - }); - cy.get(cesc("#\\/_p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e"); - }); - cy.get(cesc("#\\/p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e"); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{end}{backspace}1{enter}", - { force: true }, - ); - cy.get(cesc("#\\/_p1")).should("not.contain.text", "a, b, c, d, e"); - cy.get(cesc("#\\/_p1")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/_p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/_p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{end}{backspace}6{enter}", - { force: true }, - ); - cy.get(cesc("#\\/_p1")).should("contain.text", "a, b, c, d, e, f"); - cy.get(cesc("#\\/_p1")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e, f"); - }); - cy.get(cesc("#\\/_p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e, f"); - }); - cy.get(cesc("#\\/p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e, f"); - }); - cy.get(cesc("#\\/_p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e, f"); - }); - cy.get(cesc("#\\/p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e, f"); - }); - }); - - it("property children account for replacement changes, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

- - - -

- -

$_aslist1{name="al2"}

- $_p1{name="p2"} - -

$al2

- $p2{name="p3"} - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/_p1")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - cy.get(cesc("#\\/_p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - cy.get(cesc("#\\/p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - cy.get(cesc("#\\/_p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - cy.get(cesc("#\\/p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type("2{enter}", { - force: true, - }); - - cy.get(cesc("#\\/_p1")).should("contain.text", "a, b"); - - cy.get(cesc("#\\/_p1")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b"); - }); - cy.get(cesc("#\\/_p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b"); - }); - cy.get(cesc("#\\/p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b"); - }); - cy.get(cesc("#\\/_p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b"); - }); - cy.get(cesc("#\\/p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b"); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{end}{backspace}5{enter}", - { force: true }, - ); - cy.get(cesc("#\\/_p1")).should("contain.text", "a, b, c, d, e"); - cy.get(cesc("#\\/_p1")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e"); - }); - cy.get(cesc("#\\/_p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e"); - }); - cy.get(cesc("#\\/p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e"); - }); - cy.get(cesc("#\\/_p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e"); - }); - cy.get(cesc("#\\/p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e"); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{end}{backspace}1{enter}", - { force: true }, - ); - cy.get(cesc("#\\/_p1")).should("not.contain.text", "a, b, c, d, e"); - cy.get(cesc("#\\/_p1")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/_p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/_p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{end}{backspace}6{enter}", - { force: true }, - ); - cy.get(cesc("#\\/_p1")).should("contain.text", "a, b, c, d, e, f"); - cy.get(cesc("#\\/_p1")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e, f"); - }); - cy.get(cesc("#\\/_p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e, f"); - }); - cy.get(cesc("#\\/p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e, f"); - }); - cy.get(cesc("#\\/_p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e, f"); - }); - cy.get(cesc("#\\/p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e, f"); - }); - }); - - it("property children account for replacement changes, with copySource", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

- - - -

- -

- -

- -

- -

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/_p1")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - cy.get(cesc("#\\/_p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - cy.get(cesc("#\\/p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - cy.get(cesc("#\\/_p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - cy.get(cesc("#\\/p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type("2{enter}", { - force: true, - }); - - cy.get(cesc("#\\/_p1")).should("contain.text", "a, b"); - - cy.get(cesc("#\\/_p1")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b"); - }); - cy.get(cesc("#\\/_p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b"); - }); - cy.get(cesc("#\\/p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b"); - }); - cy.get(cesc("#\\/_p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b"); - }); - cy.get(cesc("#\\/p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b"); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{end}{backspace}5{enter}", - { force: true }, - ); - cy.get(cesc("#\\/_p1")).should("contain.text", "a, b, c, d, e"); - cy.get(cesc("#\\/_p1")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e"); - }); - cy.get(cesc("#\\/_p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e"); - }); - cy.get(cesc("#\\/p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e"); - }); - cy.get(cesc("#\\/_p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e"); - }); - cy.get(cesc("#\\/p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e"); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{end}{backspace}1{enter}", - { force: true }, - ); - cy.get(cesc("#\\/_p1")).should("not.contain.text", "a, b, c, d, e"); - cy.get(cesc("#\\/_p1")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/_p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/_p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - cy.get(cesc("#\\/p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a"); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{end}{backspace}6{enter}", - { force: true }, - ); - cy.get(cesc("#\\/_p1")).should("contain.text", "a, b, c, d, e, f"); - cy.get(cesc("#\\/_p1")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e, f"); - }); - cy.get(cesc("#\\/_p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e, f"); - }); - cy.get(cesc("#\\/p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e, f"); - }); - cy.get(cesc("#\\/_p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e, f"); - }); - cy.get(cesc("#\\/p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("a, b, c, d, e, f"); - }); - }); - - it("copy macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

a=

-

b=

-

c=

- -

ax^2+bx+c = $a x^2 + $b x + $c

-

ax^2+bx+c = $s

-

ax^2+bx+c = $$s

-

ax^2+bx+c = $$$s

-

$_m1

-

$$_m1

-

$$$_m1

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/orig")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("ax2+bx+c=5x2+2x+3"); - }); - cy.get(cesc("#\\/single")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("ax2+bx+c=5x2+2x+3"); - }); - cy.get(cesc("#\\/double")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("ax2+bx+c=$$s"); - }); - cy.get(cesc("#\\/triple")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("ax2+bx+c=$$$s"); - }); - cy.get(cesc("#\\/singlem")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("ax2+bx+c=5x2+2x+3"); - }); - cy.get(cesc("#\\/doublem")).should("have.text", "$$_m1"); - cy.get(cesc("#\\/triplem")).should("have.text", "$$$_m1"); - - cy.log("Enter new numbers"); - cy.get(cesc("#\\/a") + " textarea").type("{end}{backspace}9{enter}", { - force: true, - }); - cy.get(cesc("#\\/b") + " textarea").type("{end}{backspace}6{enter}", { - force: true, - }); - cy.get(cesc("#\\/c") + " textarea").type("{end}{backspace}7{enter}", { - force: true, - }); - - cy.get(cesc("#\\/orig")).should("contain.text", "ax2+bx+c=9x2+6x+7"); - cy.get(cesc("#\\/orig")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("ax2+bx+c=9x2+6x+7"); - }); - cy.get(cesc("#\\/single")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("ax2+bx+c=9x2+6x+7"); - }); - cy.get(cesc("#\\/double")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("ax2+bx+c=$$s"); - }); - cy.get(cesc("#\\/triple")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("ax2+bx+c=$$$s"); - }); - cy.get(cesc("#\\/singlem")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("ax2+bx+c=9x2+6x+7"); - }); - cy.get(cesc("#\\/doublem")).should("have.text", "$$_m1"); - cy.get(cesc("#\\/triplem")).should("have.text", "$$$_m1"); - }); - - it("macros after failed double macro", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - hi - bye -

$t, $$t, $ $u, - $t, $$u, $u

-

$u, $$t(, $t, - $u, $$u, $t

-

$t, $$$t, $5, $u, $$5, $t, $$$5, $u

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/_p1")).should( - "have.text", - "hi, $$t, $ bye,\n hi, $$u, bye", - ); - cy.get(cesc("#\\/_p2")).should( - "have.text", - "bye, $$t(, hi,\n bye, $$u, hi", - ); - cy.get(cesc("#\\/_p3")).should( - "have.text", - "hi, $$$t, $5, bye, $$5, hi, $$$5, bye", - ); - }); - - it("copy does not ignore hide by default", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Hidden text: secret

-

Hidden by default: $hidden

-

Force to reveal:

-

Force to reveal 2:

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/_p1")).should("have.text", "Hidden text: "); - cy.get(cesc("#\\/_p2")).should("have.text", "Hidden by default: "); - cy.get(cesc("#\\/_p3")).should("have.text", "Force to reveal: secret"); - cy.get(cesc("#\\/_p4")).should( - "have.text", - "Force to reveal 2: secret", - ); - }); - - it("copy does not ignore hide by default, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Hidden text: secret

-

Hidden by default: $hidden

-

Force to reveal: $hidden{hide="false"}

-

Force to reveal 2: $hidden{sourceAttributesToIgnore="hide"}

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/_p1")).should("have.text", "Hidden text: "); - cy.get(cesc("#\\/_p2")).should("have.text", "Hidden by default: "); - cy.get(cesc("#\\/_p3")).should("have.text", "Force to reveal: secret"); - cy.get(cesc("#\\/_p4")).should( - "have.text", - "Force to reveal 2: secret", - ); - }); - - it("copy does not ignore hide by default, with copySource", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Hidden text: secret

-

Hidden by default:

-

Force to reveal:

-

Force to reveal 2:

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/_p1")).should("have.text", "Hidden text: "); - cy.get(cesc("#\\/_p2")).should("have.text", "Hidden by default: "); - cy.get(cesc("#\\/_p3")).should("have.text", "Force to reveal: secret"); - cy.get(cesc("#\\/_p4")).should( - "have.text", - "Force to reveal 2: secret", - ); - }); - - it("copy keeps hidden children hidden", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Hidden text: secret

-

Hidden: $(theP/hidden)

-

Revealed: $(theP/hidden{hide="false"})

- -

Hidden 2: $(theP2/hidden)

-

Revealed 2: $(theP2/hidden{hide="false"})

- -

Revealed 3: $(theP3/hidden)

- -

Hidden 4: $(theP4/hidden)

-

Revealed 4: $(theP4/hidden{hide="false"})

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/theP")).should("have.text", "Hidden text: "); - cy.get(cesc("#\\/pHidden")).should("have.text", "Hidden: "); - cy.get(cesc("#\\/pReveal")).should("have.text", "Revealed: secret"); - cy.get(cesc("#\\/theP2")).should("have.text", "Hidden text: "); - cy.get(cesc("#\\/pHidden2")).should("have.text", "Hidden 2: "); - cy.get(cesc("#\\/pReveal2")).should("have.text", "Revealed 2: secret"); - cy.get(cesc("#\\/theP3")).should("have.text", "Hidden text: secret"); - cy.get(cesc("#\\/pReveal3")).should("have.text", "Revealed 3: secret"); - cy.get(cesc("#\\/theP4")).should("have.text", "Hidden text: "); - cy.get(cesc("#\\/pHidden4")).should("have.text", "Hidden 4: "); - cy.get(cesc("#\\/pReveal4")).should("have.text", "Revealed 4: secret"); - }); - - it("copy keeps hidden children hidden, all macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Hidden text: secret

-

Hidden: $(theP/hidden)

-

Revealed: $(theP/hidden{hide="false"})

- $theP{name="theP2"} -

Hidden 2: $(theP2/hidden)

-

Revealed 2: $(theP2/hidden{hide="false"})

- $theP{sourceAttributesToIgnore="hide" name="theP3"} -

Revealed 3: $(theP3/hidden)

- $theP{hide="false" name="theP4"} -

Hidden 4: $(theP4/hidden)

-

Revealed 4: $(theP4/hidden{hide="false"})

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/theP")).should("have.text", "Hidden text: "); - cy.get(cesc("#\\/pHidden")).should("have.text", "Hidden: "); - cy.get(cesc("#\\/pReveal")).should("have.text", "Revealed: secret"); - cy.get(cesc("#\\/theP2")).should("have.text", "Hidden text: "); - cy.get(cesc("#\\/pHidden2")).should("have.text", "Hidden 2: "); - cy.get(cesc("#\\/pReveal2")).should("have.text", "Revealed 2: secret"); - cy.get(cesc("#\\/theP3")).should("have.text", "Hidden text: secret"); - cy.get(cesc("#\\/pReveal3")).should("have.text", "Revealed 3: secret"); - cy.get(cesc("#\\/theP4")).should("have.text", "Hidden text: "); - cy.get(cesc("#\\/pHidden4")).should("have.text", "Hidden 4: "); - cy.get(cesc("#\\/pReveal4")).should("have.text", "Revealed 4: secret"); - }); - - it("copy keeps hidden children hidden, with copySource", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Hidden text: secret

-

Hidden:

-

Revealed:

-

-

Hidden 2:

-

Revealed 2:

-

-

Revealed 3:

-

-

Hidden 4:

-

Revealed 4:

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/pHidden")).should("have.text", "Hidden: "); - cy.get(cesc("#\\/pReveal")).should("have.text", "Revealed: secret"); - cy.get(cesc("#\\/theP2")).should("have.text", "Hidden text: "); - cy.get(cesc("#\\/pHidden2")).should("have.text", "Hidden 2: "); - cy.get(cesc("#\\/pReveal2")).should("have.text", "Revealed 2: secret"); - cy.get(cesc("#\\/theP3")).should("have.text", "Hidden text: secret"); - cy.get(cesc("#\\/pReveal3")).should("have.text", "Revealed 3: secret"); - cy.get(cesc("#\\/theP4")).should("have.text", "Hidden text: "); - cy.get(cesc("#\\/pHidden4")).should("have.text", "Hidden 4: "); - cy.get(cesc("#\\/pReveal4")).should("have.text", "Revealed 4: secret"); - }); - - it("copies hide dynamically", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - hello - - - - - - - - -

copy 1:

-

copy 2:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/c1")).should("have.text", "copy 1: hello"); - cy.get(cesc("#\\/c2")).should("have.text", "copy 2: "); - - cy.get(cesc("#\\/h1")).click(); - cy.get(cesc("#\\/h2")).click(); - - cy.get(cesc("#\\/c1")).should("have.text", "copy 1: "); - cy.get(cesc("#\\/c2")).should("have.text", "copy 2: hello"); - - cy.get(cesc("#\\/h1")).click(); - cy.get(cesc("#\\/h2")).click(); - - cy.get(cesc("#\\/c1")).should("have.text", "copy 1: hello"); - cy.get(cesc("#\\/c2")).should("have.text", "copy 2: "); - }); - - it("copies hide dynamically, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - hello - - - - - - - - -

copy 1: $source{hide="$h1"}

-

copy 2: $source{hide="$h2"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/c1")).should("have.text", "copy 1: hello"); - cy.get(cesc("#\\/c2")).should("have.text", "copy 2: "); - - cy.get(cesc("#\\/h1")).click(); - cy.get(cesc("#\\/h2")).click(); - - cy.get(cesc("#\\/c1")).should("have.text", "copy 1: "); - cy.get(cesc("#\\/c2")).should("have.text", "copy 2: hello"); - - cy.get(cesc("#\\/h1")).click(); - cy.get(cesc("#\\/h2")).click(); - - cy.get(cesc("#\\/c1")).should("have.text", "copy 1: hello"); - cy.get(cesc("#\\/c2")).should("have.text", "copy 2: "); - }); - - it("copies hide dynamically, with copySource", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - hello - - - - - - - - -

copy 1:

-

copy 2:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/c1")).should("have.text", "copy 1: hello"); - cy.get(cesc("#\\/c2")).should("have.text", "copy 2: "); - - cy.get(cesc("#\\/h1")).click(); - cy.get(cesc("#\\/h2")).click(); - - cy.get(cesc("#\\/c1")).should("have.text", "copy 1: "); - cy.get(cesc("#\\/c2")).should("have.text", "copy 2: hello"); - - cy.get(cesc("#\\/h1")).click(); - cy.get(cesc("#\\/h2")).click(); - - cy.get(cesc("#\\/c1")).should("have.text", "copy 1: hello"); - cy.get(cesc("#\\/c2")).should("have.text", "copy 2: "); - }); - - it("copy uri two problems", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - Two problems - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_title1")).should("have.text", "Two problems"); // to wait for page to load - - let problem1Version; - let animalOptions = ["cat", "dog", "mouse", "fish"]; - let soundOptions = ["meow", "woof", "squeak", "blub"]; - - cy.get(cesc2("#/problem1/_title1")).should( - "have.text", - "Animal sounds", - ); - - cy.get(cesc2("#/problem1/_p1")) - .invoke("text") - .then((text) => { - let titleOptions = animalOptions.map( - (x) => `What does the ${x} say?`, - ); - problem1Version = titleOptions.indexOf(text); - expect(problem1Version).not.eq(-1); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let copy1Name = stateVariables["/problem1"].replacementOf; - let copy2Name = stateVariables["/problem2"].replacementOf; - expect(stateVariables[copy1Name].stateValues.cid).eq( - "bafkreifgmyjuw4m6odukznenshkyfupp3egx6ep3jgnlo747d6s5v7nznu", - ); - expect(stateVariables[copy1Name].stateValues.doenetId).eq( - "abcdefg", - ); - expect(stateVariables[copy2Name].stateValues.cid).eq( - "bafkreide4mismb45mxved2ibfh5jnj75kty7vjz7w6zo7goyxpwr2e7wti", - ); - expect(stateVariables[copy2Name].stateValues.doenetId).eq( - "hijklmnop", - ); - }); - }); - - cy.log(`select correct answer for problem 1`).then(() => { - let animal = animalOptions[problem1Version]; - let sound = soundOptions[problem1Version]; - cy.get(cesc2("#/problem1/_choiceinput1")) - .contains(sound) - .click({ force: true }); - cy.get(cesc2("#/problem1/_choiceinput1_submit")).click(); - cy.get(cesc2("#/problem1/_choiceinput1_correct")).should( - "be.visible", - ); - cy.get(cesc2("#/problem1/_choiceinput1_incorrect")).should( - "not.exist", - ); - cy.get(cesc2("#/problem1/_feedback1")).should( - "have.text", - `That's right, the ${animal} goes ${sound}!`, - ); - cy.get(cesc2("#/problem1/_feedback2")).should("not.exist"); - }); - - cy.log(`select incorrect answer for problem 1`).then(() => { - let incorrectInd = (problem1Version + 1) % 4; - let sound = soundOptions[incorrectInd]; - cy.get(cesc2("#/problem1/_choiceinput1")) - .contains(sound) - .click({ force: true }); - cy.get(cesc2("#/problem1/_choiceinput1_submit")).click(); - cy.get(cesc2("#/problem1/_choiceinput1_correct")).should( - "not.exist", - ); - cy.get(cesc2("#/problem1/_choiceinput1_incorrect")).should( - "be.visible", - ); - cy.get(cesc2("#/problem1/_feedback1")).should("not.exist"); - cy.get(cesc2("#/problem1/_feedback2")).should( - "have.text", - `Try again.`, - ); - }); - - cy.get(cesc2("#/problem2/_title1")).should( - "have.text", - "Derivative problem", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/problem2/_answer1"].stateValues - .inputChildren[0].componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); - let mathinputCorrectAnchor = cesc2( - "#" + mathinputName + "_correct", - ); - let mathinputIncorrectAnchor = cesc2( - "#" + mathinputName + "_incorrect", - ); - - cy.log(`enter incorrect answer for problem 2`); - cy.get(mathinputAnchor).type("2y{enter}", { force: true }); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("be.visible"); - - cy.log(`enter correct answer for problem 2`); - cy.get(mathinputAnchor).type("{end}{backspace}x", { force: true }); - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputAnchor).type("{enter}", { force: true }); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("be.visible"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - }); - }); - - it("copy uri two problems, with copyFromUri", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - Two problems - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_title1")).should("have.text", "Two problems"); // to wait for page to load - - let problem1Version; - let animalOptions = ["cat", "dog", "mouse", "fish"]; - let soundOptions = ["meow", "woof", "squeak", "blub"]; - - cy.get(cesc2("#/problem1/_title1")).should( - "have.text", - "Animal sounds", - ); - - cy.get(cesc2("#/problem1/_p1")) - .invoke("text") - .then((text) => { - let titleOptions = animalOptions.map( - (x) => `What does the ${x} say?`, - ); - problem1Version = titleOptions.indexOf(text); - expect(problem1Version).not.eq(-1); - }); - - cy.log(`select correct answer for problem 1`).then(() => { - let animal = animalOptions[problem1Version]; - let sound = soundOptions[problem1Version]; - cy.get(cesc2("#/problem1/_choiceinput1")) - .contains(sound) - .click({ force: true }); - cy.get(cesc2("#/problem1/_choiceinput1_submit")).click(); - cy.get(cesc2("#/problem1/_choiceinput1_correct")).should( - "be.visible", - ); - cy.get(cesc2("#/problem1/_choiceinput1_incorrect")).should( - "not.exist", - ); - cy.get(cesc2("#/problem1/_feedback1")).should( - "have.text", - `That's right, the ${animal} goes ${sound}!`, - ); - cy.get(cesc2("#/problem1/_feedback2")).should("not.exist"); - }); - - cy.log(`select incorrect answer for problem 1`).then(() => { - let incorrectInd = (problem1Version + 1) % 4; - let sound = soundOptions[incorrectInd]; - cy.get(cesc2("#/problem1/_choiceinput1")) - .contains(sound) - .click({ force: true }); - cy.get(cesc2("#/problem1/_choiceinput1_submit")).click(); - cy.get(cesc2("#/problem1/_choiceinput1_correct")).should( - "not.exist", - ); - cy.get(cesc2("#/problem1/_choiceinput1_incorrect")).should( - "be.visible", - ); - cy.get(cesc2("#/problem1/_feedback1")).should("not.exist"); - cy.get(cesc2("#/problem1/_feedback2")).should( - "have.text", - `Try again.`, - ); - }); - - cy.get(cesc2("#/problem2/_title1")).should( - "have.text", - "Derivative problem", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/problem2/_answer1"].stateValues - .inputChildren[0].componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); - let mathinputCorrectAnchor = cesc2( - "#" + mathinputName + "_correct", - ); - let mathinputIncorrectAnchor = cesc2( - "#" + mathinputName + "_incorrect", - ); - - cy.log(`enter incorrect answer for problem 2`); - cy.get(mathinputAnchor).type("2y{enter}", { force: true }); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("be.visible"); - - cy.log(`enter correct answer for problem 2`); - cy.get(mathinputAnchor).type("{end}{backspace}x", { force: true }); - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputAnchor).type("{enter}", { force: true }); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("be.visible"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - }); - }); - - it("copy uri two problems, with copyFromUri, change titles, add content, change attribute", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - Two problems - - - Extra animal sounds - -

New content at bottom

-
- - - Derivative with second derivative - -

What is the second derivative of ? - - - $(problem2/_derivative1) - - -

-
- -

End paragraph

- `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_title1")).should("have.text", "Two problems"); // to wait for page to load - - let problem1Version; - let animalOptions = ["cat", "dog", "mouse", "fish"]; - let soundOptions = ["meow", "woof", "squeak", "blub"]; - - cy.get(cesc2("#/problem1/_title1")).should("not.exist"); - cy.get(cesc2("#/_title2")).should("have.text", "Extra animal sounds"); - cy.get(cesc2("#/_p1")).should("have.text", "New content at bottom"); - cy.get(cesc2("#/_p3")).should("have.text", "End paragraph"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/problem1"].stateValues.title).eq( - "Extra animal sounds", - ); - }); - - cy.get(cesc2("#/problem1/_p1")) - .invoke("text") - .then((text) => { - let titleOptions = animalOptions.map( - (x) => `What does the ${x} say?`, - ); - problem1Version = titleOptions.indexOf(text); - expect(problem1Version).not.eq(-1); - }); - - cy.log(`select correct answer for problem 1`).then(() => { - let animal = animalOptions[problem1Version]; - let sound = soundOptions[problem1Version]; - cy.get(cesc2("#/problem1/_choiceinput1")) - .contains(sound) - .click({ force: true }); - cy.get(cesc2("#/problem1/_choiceinput1_submit")).click(); - cy.get(cesc2("#/problem1/_choiceinput1_correct")).should( - "be.visible", - ); - cy.get(cesc2("#/problem1/_choiceinput1_incorrect")).should( - "not.exist", - ); - cy.get(cesc2("#/problem1/_feedback1")).should( - "have.text", - `That's right, the ${animal} goes ${sound}!`, - ); - cy.get(cesc2("#/problem1/_feedback2")).should("not.exist"); - }); - - cy.log(`select incorrect answer for problem 1`).then(() => { - let incorrectInd = (problem1Version + 1) % 4; - let sound = soundOptions[incorrectInd]; - cy.get(cesc2("#/problem1/_choiceinput1")) - .contains(sound) - .click({ force: true }); - cy.get(cesc2("#/problem1/_choiceinput1_submit")).click(); - cy.get(cesc2("#/problem1/_choiceinput1_correct")).should( - "not.exist", - ); - cy.get(cesc2("#/problem1/_choiceinput1_incorrect")).should( - "be.visible", - ); - cy.get(cesc2("#/problem1/_feedback1")).should("not.exist"); - cy.get(cesc2("#/problem1/_feedback2")).should( - "have.text", - `Try again.`, - ); - }); - - cy.get(cesc2("#/problem2/_title1")).should("not.exist"); - cy.get(cesc2("#/_title3")).should( - "have.text", - "Derivative with second derivative", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/problem2/_answer1"].stateValues - .inputChildren[0].componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - - let mathinput2Name = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinput2Anchor = cesc2("#" + mathinput2Name) + " textarea"; - - expect(stateVariables["/problem2"].stateValues.title).eq( - "Derivative with second derivative", - ); - - cy.log(`enter incorrect answer for problem 2`); - cy.get(mathinputAnchor).type("2y{enter}", { force: true }); - cy.get(cesc2("#/problem2_submit")).click(); - cy.get(cesc2("#/problem2_incorrect")).should("be.visible"); - - cy.log(`enter correct answer for problem 2`); - cy.get(mathinputAnchor).type("{end}{backspace}x", { force: true }); - cy.get(cesc2("#/problem2_submit")).click(); - cy.get(cesc2("#/problem2_partial")).should("contain.text", "50%"); - - cy.log(`enter incorrect answer for problem 2, part 2`); - cy.get(mathinput2Anchor).type("3{enter}", { force: true }); - cy.get(cesc2("#/problem2_submit")).click(); - cy.get(cesc2("#/problem2_partial")).should("contain.text", "50%"); - - cy.log(`enter correct answer for problem 2, part 2`); - cy.get(mathinput2Anchor).type("{end}{backspace}2", { force: true }); - cy.get(cesc2("#/problem2_submit")).click(); - cy.get(cesc2("#/problem2_correct")).should("be.visible"); - }); - }); - - it("copy uri two problems, with copyFromUri, newNamespace change titles, add content, change attribute", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - Two problems - - - Extra animal sounds - -

New content at bottom

-
- - - Derivative with second derivative - -

What is the second derivative of ? - - - $_derivative1 - - -

-
- -

End paragraph

- `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_title1")).should("have.text", "Two problems"); // to wait for page to load - - let problem1Version; - let animalOptions = ["cat", "dog", "mouse", "fish"]; - let soundOptions = ["meow", "woof", "squeak", "blub"]; - - cy.get(cesc2("#/problem1/_title1")).should("not.exist"); - cy.get(cesc2("#/problem1/_title2")).should( - "have.text", - "Extra animal sounds", - ); - cy.get(cesc2("#/problem1/_p4")).should( - "have.text", - "New content at bottom", - ); - cy.get(cesc2("#/_p1")).should("have.text", "End paragraph"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/problem1"].stateValues.title).eq( - "Extra animal sounds", - ); - }); - - cy.get(cesc2("#/problem1/_p1")) - .invoke("text") - .then((text) => { - let titleOptions = animalOptions.map( - (x) => `What does the ${x} say?`, - ); - problem1Version = titleOptions.indexOf(text); - expect(problem1Version).not.eq(-1); - }); - - cy.log(`select correct answer for problem 1`).then(() => { - let animal = animalOptions[problem1Version]; - let sound = soundOptions[problem1Version]; - cy.get(cesc2("#/problem1/_choiceinput1")) - .contains(sound) - .click({ force: true }); - cy.get(cesc2("#/problem1/_choiceinput1_submit")).click(); - cy.get(cesc2("#/problem1/_choiceinput1_correct")).should( - "be.visible", - ); - cy.get(cesc2("#/problem1/_choiceinput1_incorrect")).should( - "not.exist", - ); - cy.get(cesc2("#/problem1/_feedback1")).should( - "have.text", - `That's right, the ${animal} goes ${sound}!`, - ); - cy.get(cesc2("#/problem1/_feedback2")).should("not.exist"); - }); - - cy.log(`select incorrect answer for problem 1`).then(() => { - let incorrectInd = (problem1Version + 1) % 4; - let sound = soundOptions[incorrectInd]; - cy.get(cesc2("#/problem1/_choiceinput1")) - .contains(sound) - .click({ force: true }); - cy.get(cesc2("#/problem1/_choiceinput1_submit")).click(); - cy.get(cesc2("#/problem1/_choiceinput1_correct")).should( - "not.exist", - ); - cy.get(cesc2("#/problem1/_choiceinput1_incorrect")).should( - "be.visible", - ); - cy.get(cesc2("#/problem1/_feedback1")).should("not.exist"); - cy.get(cesc2("#/problem1/_feedback2")).should( - "have.text", - `Try again.`, - ); - }); - - cy.get(cesc2("#/problem2/_title1")).should("not.exist"); - cy.get(cesc2("#/problem2/_title2")).should( - "have.text", - "Derivative with second derivative", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/problem2/_answer1"].stateValues - .inputChildren[0].componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - - let mathinput2Name = - stateVariables["/problem2/_answer2"].stateValues - .inputChildren[0].componentName; - let mathinput2Anchor = cesc2("#" + mathinput2Name) + " textarea"; - - expect(stateVariables["/problem2"].stateValues.title).eq( - "Derivative with second derivative", - ); - - cy.log(`enter incorrect answer for problem 2`); - cy.get(mathinputAnchor).type("2y{enter}", { force: true }); - cy.get(cesc2("#/problem2_submit")).click(); - cy.get(cesc2("#/problem2_incorrect")).should("be.visible"); - - cy.log(`enter correct answer for problem 2`); - cy.get(mathinputAnchor).type("{end}{backspace}x", { force: true }); - cy.get(cesc2("#/problem2_submit")).click(); - cy.get(cesc2("#/problem2_partial")).should("contain.text", "50%"); - - cy.log(`enter incorrect answer for problem 2, part 2`); - cy.get(mathinput2Anchor).type("3{enter}", { force: true }); - cy.get(cesc2("#/problem2_submit")).click(); - cy.get(cesc2("#/problem2_partial")).should("contain.text", "50%"); - - cy.log(`enter correct answer for problem 2, part 2`); - cy.get(mathinput2Anchor).type("{end}{backspace}2", { force: true }); - cy.get(cesc2("#/problem2_submit")).click(); - cy.get(cesc2("#/problem2_correct")).should("be.visible"); - }); - }); - - it("copy uri two problems, change attribute but cannot change titles or add content without copyFromUri", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - Two problems - - - Extra animal sounds - -

New content at bottom

-
- - - Derivative with second derivative - -

What is the second derivative of ? - - - $(problem2/_derivative1) - - -

-
-

End paragraph

- - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_title1")).should("have.text", "Two problems"); // to wait for page to load - - let problem1Version; - let animalOptions = ["cat", "dog", "mouse", "fish"]; - let soundOptions = ["meow", "woof", "squeak", "blub"]; - - cy.get(cesc2("#/problem1/_title1")).should( - "have.text", - "Animal sounds", - ); - cy.get(cesc2("#/_title2")).should("not.exist"); - cy.get(cesc2("#/_p1")).should("not.exist"); - cy.get(cesc2("#/_p3")).should("have.text", "End paragraph"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/problem1"].stateValues.title).eq( - "Animal sounds", - ); - }); - - cy.get(cesc2("#/problem1/_p1")) - .invoke("text") - .then((text) => { - let titleOptions = animalOptions.map( - (x) => `What does the ${x} say?`, - ); - problem1Version = titleOptions.indexOf(text); - expect(problem1Version).not.eq(-1); - }); - - cy.log(`select correct answer for problem 1`).then(() => { - let animal = animalOptions[problem1Version]; - let sound = soundOptions[problem1Version]; - cy.get(cesc2("#/problem1/_choiceinput1")) - .contains(sound) - .click({ force: true }); - cy.get(cesc2("#/problem1/_choiceinput1_submit")).click(); - cy.get(cesc2("#/problem1/_choiceinput1_correct")).should( - "be.visible", - ); - cy.get(cesc2("#/problem1/_choiceinput1_incorrect")).should( - "not.exist", - ); - cy.get(cesc2("#/problem1/_feedback1")).should( - "have.text", - `That's right, the ${animal} goes ${sound}!`, - ); - cy.get(cesc2("#/problem1/_feedback2")).should("not.exist"); - }); - - cy.log(`select incorrect answer for problem 1`).then(() => { - let incorrectInd = (problem1Version + 1) % 4; - let sound = soundOptions[incorrectInd]; - cy.get(cesc2("#/problem1/_choiceinput1")) - .contains(sound) - .click({ force: true }); - cy.get(cesc2("#/problem1/_choiceinput1_submit")).click(); - cy.get(cesc2("#/problem1/_choiceinput1_correct")).should( - "not.exist", - ); - cy.get(cesc2("#/problem1/_choiceinput1_incorrect")).should( - "be.visible", - ); - cy.get(cesc2("#/problem1/_feedback1")).should("not.exist"); - cy.get(cesc2("#/problem1/_feedback2")).should( - "have.text", - `Try again.`, - ); - }); - - cy.get(cesc2("#/problem2/_title1")).should( - "have.text", - "Derivative problem", - ); - cy.get(cesc2("#/_title3")).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/problem2/_answer1"].stateValues - .inputChildren[0].componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - - expect(stateVariables["/_answer1"]).eq(undefined); - - expect(stateVariables["/problem2"].stateValues.title).eq( - "Derivative problem", - ); - - cy.log(`enter incorrect answer for problem 2`); - cy.get(mathinputAnchor).type("2y{enter}", { force: true }); - cy.get(cesc2("#/problem2_submit")).click(); - cy.get(cesc2("#/problem2_incorrect")).should("be.visible"); - - cy.log(`enter correct answer for problem 2`); - cy.get(mathinputAnchor).type("{end}{backspace}x", { force: true }); - cy.get(cesc2("#/problem2_submit")).click(); - cy.get(cesc2("#/problem2_correct")).should("be.visible"); - }); - }); - - it("copy uri containing copy uri of two problems", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - Four problems - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_title1")).should("have.text", "Four problems"); // to wait for page to load - - let problem1Version; - let animalOptions = ["cat", "dog", "mouse", "fish"]; - let soundOptions = ["meow", "woof", "squeak", "blub"]; - - cy.get(cesc2("#/problem12/problem1/_p1")) - .invoke("text") - .then((text) => { - let titleOptions = animalOptions.map( - (x) => `What does the ${x} say?`, - ); - problem1Version = titleOptions.indexOf(text); - expect(problem1Version).not.eq(-1); - }); - - cy.log(`select correct answer for problem 1`).then(() => { - let animal = animalOptions[problem1Version]; - let sound = soundOptions[problem1Version]; - cy.get(cesc2("#/problem12/problem1/_choiceinput1")) - .contains(sound) - .click({ force: true }); - cy.get(cesc2("#/problem12/problem1/_choiceinput1_submit")).click(); - cy.get(cesc2("#/problem12/problem1/_choiceinput1_correct")).should( - "be.visible", - ); - cy.get( - cesc2("#/problem12/problem1/_choiceinput1_incorrect"), - ).should("not.exist"); - cy.get(cesc2("#/problem12/problem1/_feedback1")).should( - "have.text", - `That's right, the ${animal} goes ${sound}!`, - ); - cy.get(cesc2("#/problem12/problem1/_feedback2")).should( - "not.exist", - ); - }); - - cy.log(`select incorrect answer for problem 1`).then(() => { - let incorrectInd = (problem1Version + 1) % 4; - let sound = soundOptions[incorrectInd]; - cy.get(cesc2("#/problem12/problem1/_choiceinput1")) - .contains(sound) - .click({ force: true }); - cy.get(cesc2("#/problem12/problem1/_choiceinput1_submit")).click(); - cy.get(cesc2("#/problem12/problem1/_choiceinput1_correct")).should( - "not.exist", - ); - cy.get( - cesc2("#/problem12/problem1/_choiceinput1_incorrect"), - ).should("be.visible"); - cy.get(cesc2("#/problem12/problem1/_feedback1")).should( - "not.exist", - ); - cy.get(cesc2("#/problem12/problem1/_feedback2")).should( - "have.text", - `Try again.`, - ); - }); - - cy.get(cesc2("#/problem12/problem2/_title1")).should( - "have.text", - "Derivative problem", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/problem12/problem2/_answer1"].stateValues - .inputChildren[0].componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); - let mathinputCorrectAnchor = cesc2( - "#" + mathinputName + "_correct", - ); - let mathinputIncorrectAnchor = cesc2( - "#" + mathinputName + "_incorrect", - ); - - cy.log(`enter incorrect answer for problem 2`); - cy.get(mathinputAnchor).type("2y{enter}", { force: true }); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("be.visible"); - - cy.log(`enter correct answer for problem 2`); - cy.get(mathinputAnchor).type("{end}{backspace}x", { force: true }); - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputAnchor).type("{enter}", { force: true }); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("be.visible"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - }); - - cy.get(cesc2("#/problem34/problem1/_p1")) - .invoke("text") - .then((text) => { - let titleOptions = animalOptions.map( - (x) => `What does the ${x} say?`, - ); - problem1Version = titleOptions.indexOf(text); - expect(problem1Version).not.eq(-1); - }); - - cy.log(`select correct answer for problem 1`).then(() => { - let animal = animalOptions[problem1Version]; - let sound = soundOptions[problem1Version]; - cy.get(cesc2("#/problem34/problem1/_choiceinput1")) - .contains(sound) - .click({ force: true }); - cy.get(cesc2("#/problem34/problem1/_choiceinput1_submit")).click(); - cy.get(cesc2("#/problem34/problem1/_choiceinput1_correct")).should( - "be.visible", - ); - cy.get( - cesc2("#/problem34/problem1/_choiceinput1_incorrect"), - ).should("not.exist"); - cy.get(cesc2("#/problem34/problem1/_feedback1")).should( - "have.text", - `That's right, the ${animal} goes ${sound}!`, - ); - cy.get(cesc2("#/problem34/problem1/_feedback2")).should( - "not.exist", - ); - }); - - cy.log(`select incorrect answer for problem 1`).then(() => { - let incorrectInd = (problem1Version + 1) % 4; - let sound = soundOptions[incorrectInd]; - cy.get(cesc2("#/problem34/problem1/_choiceinput1")) - .contains(sound) - .click({ force: true }); - cy.get(cesc2("#/problem34/problem1/_choiceinput1_submit")).click(); - cy.get(cesc2("#/problem34/problem1/_choiceinput1_correct")).should( - "not.exist", - ); - cy.get( - cesc2("#/problem34/problem1/_choiceinput1_incorrect"), - ).should("be.visible"); - cy.get(cesc2("#/problem34/problem1/_feedback1")).should( - "not.exist", - ); - cy.get(cesc2("#/problem34/problem1/_feedback2")).should( - "have.text", - `Try again.`, - ); - }); - - cy.get(cesc2("#/problem34/problem2/_title1")).should( - "have.text", - "Derivative problem", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/problem34/problem2/_answer1"].stateValues - .inputChildren[0].componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); - let mathinputCorrectAnchor = cesc2( - "#" + mathinputName + "_correct", - ); - let mathinputIncorrectAnchor = cesc2( - "#" + mathinputName + "_incorrect", - ); - - cy.log(`enter incorrect answer for problem 2`); - cy.get(mathinputAnchor).type("2y{enter}", { force: true }); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("be.visible"); - - cy.log(`enter correct answer for problem 2`); - cy.get(mathinputAnchor).type("{end}{backspace}x", { force: true }); - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputAnchor).type("{enter}", { force: true }); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("be.visible"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - }); - }); - - // this triggered an error not caught with the other order - it("copy uri containing copy uri of two problems, newNamespace first", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - Four problems - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_title1")).should("have.text", "Four problems"); // to wait for page to load - - let problem1Version; - let animalOptions = ["cat", "dog", "mouse", "fish"]; - let soundOptions = ["meow", "woof", "squeak", "blub"]; - - cy.get(cesc2("#/problem12/problem1/_p1")) - .invoke("text") - .then((text) => { - let titleOptions = animalOptions.map( - (x) => `What does the ${x} say?`, - ); - problem1Version = titleOptions.indexOf(text); - expect(problem1Version).not.eq(-1); - }); - - cy.log(`select correct answer for problem 1`).then(() => { - let animal = animalOptions[problem1Version]; - let sound = soundOptions[problem1Version]; - cy.get(cesc2("#/problem12/problem1/_choiceinput1")) - .contains(sound) - .click({ force: true }); - cy.get(cesc2("#/problem12/problem1/_choiceinput1_submit")).click(); - cy.get(cesc2("#/problem12/problem1/_choiceinput1_correct")).should( - "be.visible", - ); - cy.get( - cesc2("#/problem12/problem1/_choiceinput1_incorrect"), - ).should("not.exist"); - cy.get(cesc2("#/problem12/problem1/_feedback1")).should( - "have.text", - `That's right, the ${animal} goes ${sound}!`, - ); - cy.get(cesc2("#/problem12/problem1/_feedback2")).should( - "not.exist", - ); - }); - - cy.log(`select incorrect answer for problem 1`).then(() => { - let incorrectInd = (problem1Version + 1) % 4; - let sound = soundOptions[incorrectInd]; - cy.get(cesc2("#/problem12/problem1/_choiceinput1")) - .contains(sound) - .click({ force: true }); - cy.get(cesc2("#/problem12/problem1/_choiceinput1_submit")).click(); - cy.get(cesc2("#/problem12/problem1/_choiceinput1_correct")).should( - "not.exist", - ); - cy.get( - cesc2("#/problem12/problem1/_choiceinput1_incorrect"), - ).should("be.visible"); - cy.get(cesc2("#/problem12/problem1/_feedback1")).should( - "not.exist", - ); - cy.get(cesc2("#/problem12/problem1/_feedback2")).should( - "have.text", - `Try again.`, - ); - }); - - cy.get(cesc2("#/problem12/problem2/_title1")).should( - "have.text", - "Derivative problem", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/problem12/problem2/_answer1"].stateValues - .inputChildren[0].componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); - let mathinputCorrectAnchor = cesc2( - "#" + mathinputName + "_correct", - ); - let mathinputIncorrectAnchor = cesc2( - "#" + mathinputName + "_incorrect", - ); - - cy.log(`enter incorrect answer for problem 2`); - cy.get(mathinputAnchor).type("2y{enter}", { force: true }); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("be.visible"); - - cy.log(`enter correct answer for problem 2`); - cy.get(mathinputAnchor).type("{end}{backspace}x", { force: true }); - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputAnchor).type("{enter}", { force: true }); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("be.visible"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - }); - - cy.get(cesc2("#/problem34/problem1/_p1")) - .invoke("text") - .then((text) => { - let titleOptions = animalOptions.map( - (x) => `What does the ${x} say?`, - ); - problem1Version = titleOptions.indexOf(text); - expect(problem1Version).not.eq(-1); - }); - - cy.log(`select correct answer for problem 1`).then(() => { - let animal = animalOptions[problem1Version]; - let sound = soundOptions[problem1Version]; - cy.get(cesc2("#/problem34/problem1/_choiceinput1")) - .contains(sound) - .click({ force: true }); - cy.get(cesc2("#/problem34/problem1/_choiceinput1_submit")).click(); - cy.get(cesc2("#/problem34/problem1/_choiceinput1_correct")).should( - "be.visible", - ); - cy.get( - cesc2("#/problem34/problem1/_choiceinput1_incorrect"), - ).should("not.exist"); - cy.get(cesc2("#/problem34/problem1/_feedback1")).should( - "have.text", - `That's right, the ${animal} goes ${sound}!`, - ); - cy.get(cesc2("#/problem34/problem1/_feedback2")).should( - "not.exist", - ); - }); - - cy.log(`select incorrect answer for problem 1`).then(() => { - let incorrectInd = (problem1Version + 1) % 4; - let sound = soundOptions[incorrectInd]; - cy.get(cesc2("#/problem34/problem1/_choiceinput1")) - .contains(sound) - .click({ force: true }); - cy.get(cesc2("#/problem34/problem1/_choiceinput1_submit")).click(); - cy.get(cesc2("#/problem34/problem1/_choiceinput1_correct")).should( - "not.exist", - ); - cy.get( - cesc2("#/problem34/problem1/_choiceinput1_incorrect"), - ).should("be.visible"); - cy.get(cesc2("#/problem34/problem1/_feedback1")).should( - "not.exist", - ); - cy.get(cesc2("#/problem34/problem1/_feedback2")).should( - "have.text", - `Try again.`, - ); - }); - - cy.get(cesc2("#/problem34/problem2/_title1")).should( - "have.text", - "Derivative problem", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinputName = - stateVariables["/problem34/problem2/_answer1"].stateValues - .inputChildren[0].componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); - let mathinputCorrectAnchor = cesc2( - "#" + mathinputName + "_correct", - ); - let mathinputIncorrectAnchor = cesc2( - "#" + mathinputName + "_incorrect", - ); - - cy.log(`enter incorrect answer for problem 2`); - cy.get(mathinputAnchor).type("2y{enter}", { force: true }); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("not.exist"); - cy.get(mathinputIncorrectAnchor).should("be.visible"); - - cy.log(`enter correct answer for problem 2`); - cy.get(mathinputAnchor).type("{end}{backspace}x", { force: true }); - cy.get(mathinputSubmitAnchor).should("be.visible"); - cy.get(mathinputAnchor).type("{enter}", { force: true }); - cy.get(mathinputSubmitAnchor).should("not.exist"); - cy.get(mathinputCorrectAnchor).should("be.visible"); - cy.get(mathinputIncorrectAnchor).should("not.exist"); - }); - }); - - it("copy uri containing variant control", () => { - const doenetML = ` - Two variants from copied document - - - `; - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: 1, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_title1")).should( - "have.text", - "Two variants from copied document", - ); // to wait for page to load - - cy.get(cesc("#\\/thedoc")).should("contain.text", "first"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect( - stateVariables["/thedoc"].sharedParameters.allPossibleVariants, - ).eqls(["first", "last"]); - expect(stateVariables["/thedoc"].sharedParameters.variantName).eq( - "first", - ); - expect( - stateVariables["/_document1"].sharedParameters - .allPossibleVariants, - ).eqls(["a", "b"]); - expect( - stateVariables["/_document1"].sharedParameters.variantName, - ).eq("a"); - }); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: 2, - }, - "*", - ); - }); - - cy.get(cesc("#\\/thedoc")).should("contain.text", "last"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect( - stateVariables["/thedoc"].sharedParameters.allPossibleVariants, - ).eqls(["first", "last"]); - expect(stateVariables["/thedoc"].sharedParameters.variantName).eq( - "last", - ); - expect( - stateVariables["/_document1"].sharedParameters - .allPossibleVariants, - ).eqls(["a", "b"]); - expect( - stateVariables["/_document1"].sharedParameters.variantName, - ).eq("b"); - }); - }); - - it("copy uri not in a problem", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/problem1_title")).should("have.text", "Animal sounds"); - - let problem1Version; - let animalOptions = ["cat", "dog", "mouse", "fish"]; - let soundOptions = ["meow", "woof", "squeak", "blub"]; - - cy.get(cesc2("#/problem1/_p1")) - .invoke("text") - .then((text) => { - let titleOptions = animalOptions.map( - (x) => `What does the ${x} say?`, - ); - problem1Version = titleOptions.indexOf(text); - expect(problem1Version).not.eq(-1); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let copy1Name = stateVariables["/problem1"].replacementOf; - expect(stateVariables[copy1Name].stateValues.cid).eq( - "bafkreidqud3rixmphu3jufuke4rw7magtcrbrjgeo6ihkoyonsig7wciey", - ); - expect(stateVariables[copy1Name].stateValues.doenetId).eq( - "abcdefg", - ); - }); - }); - - cy.log(`select correct answer for problem 1`).then(() => { - let animal = animalOptions[problem1Version]; - let sound = soundOptions[problem1Version]; - cy.get(cesc2("#/problem1/_choiceinput1")) - .contains(sound) - .click({ force: true }); - cy.get(cesc2("#/problem1/_choiceinput1_submit")).click(); - cy.get(cesc2("#/problem1/_choiceinput1_correct")).should( - "be.visible", - ); - cy.get(cesc2("#/problem1/_choiceinput1_incorrect")).should( - "not.exist", - ); - cy.get(cesc2("#/problem1/_feedback1")).should( - "have.text", - `That's right, the ${animal} goes ${sound}!`, - ); - cy.get(cesc2("#/problem1/_feedback2")).should("not.exist"); - }); - - cy.log(`select incorrect answer for problem 1`).then(() => { - let incorrectInd = (problem1Version + 1) % 4; - let sound = soundOptions[incorrectInd]; - cy.get(cesc2("#/problem1/_choiceinput1")) - .contains(sound) - .click({ force: true }); - cy.get(cesc2("#/problem1/_choiceinput1_submit")).click(); - cy.get(cesc2("#/problem1/_choiceinput1_correct")).should( - "not.exist", - ); - cy.get(cesc2("#/problem1/_choiceinput1_incorrect")).should( - "be.visible", - ); - cy.get(cesc2("#/problem1/_feedback1")).should("not.exist"); - cy.get(cesc2("#/problem1/_feedback2")).should( - "have.text", - `Try again.`, - ); - }); - }); - - it("copyFromUri for uri not in a problem yields nothing", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/problem1_title")).should("have.text", "Problem 1"); - - cy.get(cesc("#\\/_document1")).should( - "not.contain.text", - "Animal sounds", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(Object.keys(stateVariables).length).eq(3); - }); - }); - - it("copy of component that changes away from a copy", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - jump - - -

- skip - $jump -

- - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/forVerb")).should("have.text", "jump"); - cy.get(cesc("#\\/verb2")).should("have.text", "jump"); - - cy.get(cesc("#\\/b")).click(); - cy.get(cesc("#\\/forVerb")).should("have.text", "skip"); - cy.get(cesc("#\\/verb2")).should("have.text", "skip"); - - cy.get(cesc("#\\/b")).click(); - cy.get(cesc("#\\/forVerb")).should("have.text", "jump"); - cy.get(cesc("#\\/verb2")).should("have.text", "jump"); - - cy.get(cesc("#\\/b")).click(); - cy.get(cesc("#\\/forVerb")).should("have.text", "skip"); - cy.get(cesc("#\\/verb2")).should("have.text", "skip"); - }); - - it("copy of component that changes away from a copy, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - jump - - -

- skip - $jump -

- - $verb{name="verb2"} - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/forVerb")).should("have.text", "jump"); - cy.get(cesc("#\\/verb2")).should("have.text", "jump"); - - cy.get(cesc("#\\/b")).click(); - cy.get(cesc("#\\/forVerb")).should("have.text", "skip"); - cy.get(cesc("#\\/verb2")).should("have.text", "skip"); - - cy.get(cesc("#\\/b")).click(); - cy.get(cesc("#\\/forVerb")).should("have.text", "jump"); - cy.get(cesc("#\\/verb2")).should("have.text", "jump"); - - cy.get(cesc("#\\/b")).click(); - cy.get(cesc("#\\/forVerb")).should("have.text", "skip"); - cy.get(cesc("#\\/verb2")).should("have.text", "skip"); - }); - - it("copy of component that changes away from a copy, with copySource", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - jump - - -

- skip - $jump -

- - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/forVerb")).should("have.text", "jump"); - cy.get(cesc("#\\/verb2")).should("have.text", "jump"); - - cy.get(cesc("#\\/b")).click(); - cy.get(cesc("#\\/forVerb")).should("have.text", "skip"); - cy.get(cesc("#\\/verb2")).should("have.text", "skip"); - - cy.get(cesc("#\\/b")).click(); - cy.get(cesc("#\\/forVerb")).should("have.text", "jump"); - cy.get(cesc("#\\/verb2")).should("have.text", "jump"); - - cy.get(cesc("#\\/b")).click(); - cy.get(cesc("#\\/forVerb")).should("have.text", "skip"); - cy.get(cesc("#\\/verb2")).should("have.text", "skip"); - }); - - it("copy of invalid source gives math in boolean and math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

We can't see $invalid in paragraph or $invisible in text.

- -

In math, we can: $bad + $nothing

- -

And in boolean as well: not ($missing = x)

. - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/_p1")).should( - "have.text", - "We can't see in paragraph or in text.", - ); - - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("_+_"); - }); - - cy.get(cesc("#\\/_boolean1")).should("have.text", "true"); - }); - - it("copy no link, base test", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Simplify of original:

-

Simplify of copies:

- -

Original: x +x

- -

Unlinked copy:

- -

Linked copy:

- -

Double value of original: - -

-

Double value of copy 1: - -

-

Double value of copy 2: - -

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc(`#\\/m`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - cy.get(cesc(`#\\/m2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc(`#\\/m3`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let copy1Name = stateVariables["/m2"].replacementOf; - let copy2Name = stateVariables["/m3"].replacementOf; - expect(stateVariables[copy1Name].stateValues.link).eq(false); - expect(stateVariables[copy2Name].stateValues.link).eq(true); - expect(stateVariables["/m"].stateValues.value).eqls(["*", 2, "x"]); - expect(stateVariables["/m2"].stateValues.value).eqls([ - "+", - "x", - "x", - ]); - expect(stateVariables["/m3"].stateValues.value).eqls([ - "+", - "x", - "x", - ]); - }); - - cy.log("simplify copies"); - cy.get(cesc("#\\/s2_input")).clear().type("full{enter}"); - - cy.get(cesc(`#\\/m2`)).should("contain.text", "2x"); - cy.get(cesc(`#\\/m`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - cy.get(cesc(`#\\/m2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - cy.get(cesc(`#\\/m3`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/m"].stateValues.value).eqls(["*", 2, "x"]); - expect(stateVariables["/m2"].stateValues.value).eqls(["*", 2, "x"]); - expect(stateVariables["/m3"].stateValues.value).eqls(["*", 2, "x"]); - }); - - cy.log("stop simplifying original"); - cy.get(cesc("#\\/s1_input")).clear().type("none{enter}"); - - cy.get(cesc(`#\\/m`)).should("contain.text", "x+x"); - - cy.get(cesc(`#\\/m`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc(`#\\/m2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - cy.get(cesc(`#\\/m3`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/m"].stateValues.value).eqls([ - "+", - "x", - "x", - ]); - expect(stateVariables["/m2"].stateValues.value).eqls(["*", 2, "x"]); - expect(stateVariables["/m3"].stateValues.value).eqls(["*", 2, "x"]); - }); - - cy.log("double original"); - cy.get(cesc("#\\/doubleOriginal_button")).click(); - - cy.get(cesc(`#\\/m`)).should("contain.text", "2(x+x)"); - - cy.get(cesc(`#\\/m`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2(x+x)"); - }); - cy.get(cesc(`#\\/m2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - cy.get(cesc(`#\\/m3`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("4x"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/m"].stateValues.value).eqls([ - "*", - 2, - ["+", "x", "x"], - ]); - expect(stateVariables["/m2"].stateValues.value).eqls(["*", 2, "x"]); - expect(stateVariables["/m3"].stateValues.value).eqls(["*", 4, "x"]); - }); - - cy.log("double copy1"); - cy.get(cesc("#\\/doubleCopy1_button")).click(); - - cy.get(cesc(`#\\/m2`)).should("contain.text", "4x"); - - cy.get(cesc(`#\\/m`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2(x+x)"); - }); - cy.get(cesc(`#\\/m2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("4x"); - }); - cy.get(cesc(`#\\/m3`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("4x"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/m"].stateValues.value).eqls([ - "*", - 2, - ["+", "x", "x"], - ]); - expect(stateVariables["/m2"].stateValues.value).eqls(["*", 4, "x"]); - expect(stateVariables["/m3"].stateValues.value).eqls(["*", 4, "x"]); - }); - - cy.log("double copy2"); - cy.get(cesc("#\\/doubleCopy2_button")).click(); - - cy.get(cesc(`#\\/m3`)).should("contain.text", "8x"); - - cy.get(cesc(`#\\/m`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2⋅4x"); - }); - cy.get(cesc(`#\\/m2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("4x"); - }); - cy.get(cesc(`#\\/m3`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("8x"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/m"].stateValues.value).eqls([ - "*", - 2, - 4, - "x", - ]); - expect(stateVariables["/m2"].stateValues.value).eqls(["*", 4, "x"]); - expect(stateVariables["/m3"].stateValues.value).eqls(["*", 8, "x"]); - }); - - cy.log("stop simplifying copies"); - cy.get(cesc("#\\/s2_input")).clear().type("none{enter}"); - - cy.get(cesc(`#\\/m2`)).should("contain.text", "2⋅2x"); - - cy.get(cesc(`#\\/m`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2⋅4x"); - }); - cy.get(cesc(`#\\/m2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2⋅2x"); - }); - cy.get(cesc(`#\\/m3`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2⋅4x"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/m"].stateValues.value).eqls([ - "*", - 2, - 4, - "x", - ]); - expect(stateVariables["/m2"].stateValues.value).eqls([ - "*", - 2, - 2, - "x", - ]); - expect(stateVariables["/m3"].stateValues.value).eqls([ - "*", - 2, - 4, - "x", - ]); - }); - }); - - it("copy no link, base test, with copySource", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Simplify of original:

-

Simplify of copies:

- -

Original: x +x

- -

Unlinked copy:

- -

Linked copy:

- -

Double value of original: - -

-

Double value of copy 1: - -

-

Double value of copy 2: - -

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc(`#\\/m`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - cy.get(cesc(`#\\/m2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc(`#\\/m3`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let copy1Name = stateVariables["/m2"].replacementOf; - let copy2Name = stateVariables["/m3"].replacementOf; - expect(stateVariables[copy1Name].stateValues.link).eq(false); - expect(stateVariables[copy2Name].stateValues.link).eq(true); - expect(stateVariables["/m"].stateValues.value).eqls(["*", 2, "x"]); - expect(stateVariables["/m2"].stateValues.value).eqls([ - "+", - "x", - "x", - ]); - expect(stateVariables["/m3"].stateValues.value).eqls([ - "+", - "x", - "x", - ]); - }); - - cy.log("simplify copies"); - cy.get(cesc("#\\/s2_input")).clear().type("full{enter}"); - - cy.get(cesc(`#\\/m2`)).should("contain.text", "2x"); - cy.get(cesc(`#\\/m`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - cy.get(cesc(`#\\/m2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - cy.get(cesc(`#\\/m3`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/m"].stateValues.value).eqls(["*", 2, "x"]); - expect(stateVariables["/m2"].stateValues.value).eqls(["*", 2, "x"]); - expect(stateVariables["/m3"].stateValues.value).eqls(["*", 2, "x"]); - }); - - cy.log("stop simplifying original"); - cy.get(cesc("#\\/s1_input")).clear().type("none{enter}"); - - cy.get(cesc(`#\\/m`)).should("contain.text", "x+x"); - - cy.get(cesc(`#\\/m`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc(`#\\/m2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - cy.get(cesc(`#\\/m3`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/m"].stateValues.value).eqls([ - "+", - "x", - "x", - ]); - expect(stateVariables["/m2"].stateValues.value).eqls(["*", 2, "x"]); - expect(stateVariables["/m3"].stateValues.value).eqls(["*", 2, "x"]); - }); - - cy.log("double original"); - cy.get(cesc("#\\/doubleOriginal_button")).click(); - - cy.get(cesc(`#\\/m`)).should("contain.text", "2(x+x)"); - - cy.get(cesc(`#\\/m`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2(x+x)"); - }); - cy.get(cesc(`#\\/m2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - cy.get(cesc(`#\\/m3`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("4x"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/m"].stateValues.value).eqls([ - "*", - 2, - ["+", "x", "x"], - ]); - expect(stateVariables["/m2"].stateValues.value).eqls(["*", 2, "x"]); - expect(stateVariables["/m3"].stateValues.value).eqls(["*", 4, "x"]); - }); - - cy.log("double copy1"); - cy.get(cesc("#\\/doubleCopy1_button")).click(); - - cy.get(cesc(`#\\/m2`)).should("contain.text", "4x"); - - cy.get(cesc(`#\\/m`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2(x+x)"); - }); - cy.get(cesc(`#\\/m2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("4x"); - }); - cy.get(cesc(`#\\/m3`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("4x"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/m"].stateValues.value).eqls([ - "*", - 2, - ["+", "x", "x"], - ]); - expect(stateVariables["/m2"].stateValues.value).eqls(["*", 4, "x"]); - expect(stateVariables["/m3"].stateValues.value).eqls(["*", 4, "x"]); - }); - - cy.log("double copy2"); - cy.get(cesc("#\\/doubleCopy2_button")).click(); - - cy.get(cesc(`#\\/m3`)).should("contain.text", "8x"); - - cy.get(cesc(`#\\/m`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2⋅4x"); - }); - cy.get(cesc(`#\\/m2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("4x"); - }); - cy.get(cesc(`#\\/m3`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("8x"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/m"].stateValues.value).eqls([ - "*", - 2, - 4, - "x", - ]); - expect(stateVariables["/m2"].stateValues.value).eqls(["*", 4, "x"]); - expect(stateVariables["/m3"].stateValues.value).eqls(["*", 8, "x"]); - }); - - cy.log("stop simplifying copies"); - cy.get(cesc("#\\/s2_input")).clear().type("none{enter}"); - - cy.get(cesc(`#\\/m2`)).should("contain.text", "2⋅2x"); - - cy.get(cesc(`#\\/m`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2⋅4x"); - }); - cy.get(cesc(`#\\/m2`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2⋅2x"); - }); - cy.get(cesc(`#\\/m3`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2⋅4x"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/m"].stateValues.value).eqls([ - "*", - 2, - 4, - "x", - ]); - expect(stateVariables["/m2"].stateValues.value).eqls([ - "*", - 2, - 2, - "x", - ]); - expect(stateVariables["/m3"].stateValues.value).eqls([ - "*", - 2, - 4, - "x", - ]); - }); - }); - - it("copy points and lines with no link", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - (1,2) - (3,4) - - - - - - - - - - - - - - - - - - - -

- - - - - - - - - - - - -

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc(`#\\/Ax`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let copyForA2 = stateVariables["/A2"].replacementOf; - let copyForl2 = stateVariables["/l2"].replacementOf; - let copyForA3 = stateVariables["/A3"].replacementOf; - let copyForA4B4 = stateVariables["/A4"].replacementOf; - let copyForgnolink = stateVariables["/gnolink"].replacementOf; - let copyForAx = stateVariables["/Ax"].replacementOf; - expect(stateVariables[copyForA2].stateValues.link).eq(false); - expect(stateVariables[copyForl2].stateValues.link).eq(false); - expect(stateVariables[copyForA3].stateValues.link).eq(false); - expect(stateVariables[copyForA4B4].stateValues.link).eq(false); - expect(stateVariables[copyForgnolink].stateValues.link).eq(false); - expect(stateVariables[copyForAx].stateValues.link).eq(false); - expect(stateVariables["/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/l"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A2"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move A"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/A", - args: { x: -9, y: -3 }, - }); - }); - - cy.get(cesc("#\\/Ac")).should( - "contain.text", - `(${nInDOM(-9)},${nInDOM(-3)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-9, -3]); - expect(stateVariables["/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/l"].stateValues.point1).eqls([-9, -3]); - expect(stateVariables["/l"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A2"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move B"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/B", - args: { x: -2, y: 6 }, - }); - }); - - cy.get(cesc("#\\/Bc")).should( - "contain.text", - `(${nInDOM(-2)},${nInDOM(6)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-9, -3]); - expect(stateVariables["/B"].stateValues.xs).eqls([-2, 6]); - expect(stateVariables["/l"].stateValues.point1).eqls([-9, -3]); - expect(stateVariables["/l"].stateValues.point2).eqls([-2, 6]); - expect(stateVariables["/A2"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move l"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveLine", - componentName: "/l", - args: { - point1coords: [-7, -6], - point2coords: [8, 0], - }, - }); - }); - - cy.get(cesc("#\\/lp1")).should( - "contain.text", - `(${nInDOM(-7)},${nInDOM(-6)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move A2"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/A2", - args: { x: 5, y: 4 }, - }); - }); - - cy.get(cesc("#\\/A2c")).should( - "contain.text", - `(${nInDOM(5)},${nInDOM(4)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move l2"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveLine", - componentName: "/l2", - args: { - point1coords: [-5, 9], - point2coords: [-4, -1], - }, - }); - }); - - cy.get(cesc("#\\/l2p1")).should( - "contain.text", - `(${nInDOM(-5)},${nInDOM(9)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move A3"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/A3", - args: { x: 6, y: -3 }, - }); - }); - - cy.get(cesc("#\\/A3c")).should( - "contain.text", - `(${nInDOM(6)},${nInDOM(-3)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move A4"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/A4", - args: { x: -2, y: 7 }, - }); - }); - - cy.get(cesc("#\\/A4c")).should( - "contain.text", - `(${nInDOM(-2)},${nInDOM(7)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([-2, 7]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move B4"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/B4", - args: { x: -9, y: -8 }, - }); - }); - - cy.get(cesc("#\\/B4c")).should( - "contain.text", - `(${nInDOM(-9)},${nInDOM(-8)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([-2, 7]); - expect(stateVariables["/B4"].stateValues.xs).eqls([-9, -8]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move A5"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/gnolink/A", - args: { x: -10, y: -9 }, - }); - }); - - cy.get(cesc("#\\/A5c")).should( - "contain.text", - `(${nInDOM(-10)},${nInDOM(-9)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([-2, 7]); - expect(stateVariables["/B4"].stateValues.xs).eqls([-9, -8]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([-10, -9]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - -10, -9, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move B5"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/gnolink/B", - args: { x: -8, y: -7 }, - }); - }); - - cy.get(cesc("#\\/B5c")).should( - "contain.text", - `(${nInDOM(-8)},${nInDOM(-7)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([-2, 7]); - expect(stateVariables["/B4"].stateValues.xs).eqls([-9, -8]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([-10, -9]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([-8, -7]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - -10, -9, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - -8, -7, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move l3"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveLine", - componentName: "/gnolink/l", - args: { - point1coords: [6, 5], - point2coords: [4, -3], - }, - }); - }); - - cy.get(cesc("#\\/l3p1")).should( - "contain.text", - `(${nInDOM(6)},${nInDOM(5)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([-2, 7]); - expect(stateVariables["/B4"].stateValues.xs).eqls([-9, -8]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([6, 5]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([4, -3]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 6, 5, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 4, -3, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - }); - - it("copy points and lines with no link, dot notation", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - (1,2) - (3,4) - - - - - - - - - - - - - - - - - - - -

- - - - - - - - - - - - -

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc(`#\\/Ax`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let copyForA2 = stateVariables["/A2"].replacementOf; - let copyForl2 = stateVariables["/l2"].replacementOf; - let copyForA3 = stateVariables["/A3"].replacementOf; - let copyForA4B4 = stateVariables["/A4"].replacementOf; - let copyForgnolink = stateVariables["/gnolink"].replacementOf; - let copyForAx = stateVariables["/Ax"].replacementOf; - expect(stateVariables[copyForA2].stateValues.link).eq(false); - expect(stateVariables[copyForl2].stateValues.link).eq(false); - expect(stateVariables[copyForA3].stateValues.link).eq(false); - expect(stateVariables[copyForA4B4].stateValues.link).eq(false); - expect(stateVariables[copyForgnolink].stateValues.link).eq(false); - expect(stateVariables[copyForAx].stateValues.link).eq(false); - expect(stateVariables["/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/l"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A2"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move A"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/A", - args: { x: -9, y: -3 }, - }); - }); - - cy.get(cesc("#\\/Ac")).should( - "contain.text", - `(${nInDOM(-9)},${nInDOM(-3)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-9, -3]); - expect(stateVariables["/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/l"].stateValues.point1).eqls([-9, -3]); - expect(stateVariables["/l"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A2"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move B"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/B", - args: { x: -2, y: 6 }, - }); - }); - - cy.get(cesc("#\\/Bc")).should( - "contain.text", - `(${nInDOM(-2)},${nInDOM(6)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-9, -3]); - expect(stateVariables["/B"].stateValues.xs).eqls([-2, 6]); - expect(stateVariables["/l"].stateValues.point1).eqls([-9, -3]); - expect(stateVariables["/l"].stateValues.point2).eqls([-2, 6]); - expect(stateVariables["/A2"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move l"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveLine", - componentName: "/l", - args: { - point1coords: [-7, -6], - point2coords: [8, 0], - }, - }); - }); - - cy.get(cesc("#\\/lp1")).should( - "contain.text", - `(${nInDOM(-7)},${nInDOM(-6)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move A2"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/A2", - args: { x: 5, y: 4 }, - }); - }); - - cy.get(cesc("#\\/A2c")).should( - "contain.text", - `(${nInDOM(5)},${nInDOM(4)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move l2"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveLine", - componentName: "/l2", - args: { - point1coords: [-5, 9], - point2coords: [-4, -1], - }, - }); - }); - - cy.get(cesc("#\\/l2p1")).should( - "contain.text", - `(${nInDOM(-5)},${nInDOM(9)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move A3"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/A3", - args: { x: 6, y: -3 }, - }); - }); - - cy.get(cesc("#\\/A3c")).should( - "contain.text", - `(${nInDOM(6)},${nInDOM(-3)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move A4"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/A4", - args: { x: -2, y: 7 }, - }); - }); - - cy.get(cesc("#\\/A4c")).should( - "contain.text", - `(${nInDOM(-2)},${nInDOM(7)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([-2, 7]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move B4"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/B4", - args: { x: -9, y: -8 }, - }); - }); - - cy.get(cesc("#\\/B4c")).should( - "contain.text", - `(${nInDOM(-9)},${nInDOM(-8)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([-2, 7]); - expect(stateVariables["/B4"].stateValues.xs).eqls([-9, -8]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move A5"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/gnolink/A", - args: { x: -10, y: -9 }, - }); - }); - - cy.get(cesc("#\\/A5c")).should( - "contain.text", - `(${nInDOM(-10)},${nInDOM(-9)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([-2, 7]); - expect(stateVariables["/B4"].stateValues.xs).eqls([-9, -8]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([-10, -9]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - -10, -9, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move B5"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/gnolink/B", - args: { x: -8, y: -7 }, - }); - }); - - cy.get(cesc("#\\/B5c")).should( - "contain.text", - `(${nInDOM(-8)},${nInDOM(-7)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([-2, 7]); - expect(stateVariables["/B4"].stateValues.xs).eqls([-9, -8]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([-10, -9]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([-8, -7]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - -10, -9, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - -8, -7, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move l3"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveLine", - componentName: "/gnolink/l", - args: { - point1coords: [6, 5], - point2coords: [4, -3], - }, - }); - }); - - cy.get(cesc("#\\/l3p1")).should( - "contain.text", - `(${nInDOM(6)},${nInDOM(5)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([-2, 7]); - expect(stateVariables["/B4"].stateValues.xs).eqls([-9, -8]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([6, 5]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([4, -3]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 6, 5, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 4, -3, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - }); - - it("copy points and lines with no link, dot notation, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - (1,2) - (3,4) - - - - - $A{link="false" name="A2"} - $l{link="false" name="l2"} - - - - $(l.point1{link="false" assignNames="A3"}) - - - $(l.points{link="false" assignNames="A4 B4" }) - - - $g{link="false" name="gnolink" newNamespace} - - $(A.x{link="false" assignNames="Ax" }) - -

- $A{name="Ac"} - $B{name="Bc"} - $(l.point1{assignNames="lp1"}) - $A2{name="A2c"} - $(l2.point1{assignNames="l2p1"}) - $A3{name="A3c"} - $A4{name="A4c"} - $B4{name="B4c"} - $(gnolink/A{name="A5c"}) - $(gnolink/B{name="B5c"}) - $(gnolink/l.point1{assignNames="l3p1"}) - -

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc(`#\\/Ax`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let copyForA2 = stateVariables["/A2"].replacementOf; - let copyForl2 = stateVariables["/l2"].replacementOf; - let copyForA3 = stateVariables["/A3"].replacementOf; - let copyForA4B4 = stateVariables["/A4"].replacementOf; - let copyForgnolink = stateVariables["/gnolink"].replacementOf; - let copyForAx = stateVariables["/Ax"].replacementOf; - expect(stateVariables[copyForA2].stateValues.link).eq(false); - expect(stateVariables[copyForl2].stateValues.link).eq(false); - expect(stateVariables[copyForA3].stateValues.link).eq(false); - expect(stateVariables[copyForA4B4].stateValues.link).eq(false); - expect(stateVariables[copyForgnolink].stateValues.link).eq(false); - expect(stateVariables[copyForAx].stateValues.link).eq(false); - expect(stateVariables["/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/l"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A2"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move A"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/A", - args: { x: -9, y: -3 }, - }); - }); - - cy.get(cesc("#\\/Ac")).should( - "contain.text", - `(${nInDOM(-9)},${nInDOM(-3)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-9, -3]); - expect(stateVariables["/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/l"].stateValues.point1).eqls([-9, -3]); - expect(stateVariables["/l"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A2"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move B"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/B", - args: { x: -2, y: 6 }, - }); - }); - - cy.get(cesc("#\\/Bc")).should( - "contain.text", - `(${nInDOM(-2)},${nInDOM(6)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-9, -3]); - expect(stateVariables["/B"].stateValues.xs).eqls([-2, 6]); - expect(stateVariables["/l"].stateValues.point1).eqls([-9, -3]); - expect(stateVariables["/l"].stateValues.point2).eqls([-2, 6]); - expect(stateVariables["/A2"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move l"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveLine", - componentName: "/l", - args: { - point1coords: [-7, -6], - point2coords: [8, 0], - }, - }); - }); - - cy.get(cesc("#\\/lp1")).should( - "contain.text", - `(${nInDOM(-7)},${nInDOM(-6)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move A2"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/A2", - args: { x: 5, y: 4 }, - }); - }); - - cy.get(cesc("#\\/A2c")).should( - "contain.text", - `(${nInDOM(5)},${nInDOM(4)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move l2"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveLine", - componentName: "/l2", - args: { - point1coords: [-5, 9], - point2coords: [-4, -1], - }, - }); - }); - - cy.get(cesc("#\\/l2p1")).should( - "contain.text", - `(${nInDOM(-5)},${nInDOM(9)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move A3"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/A3", - args: { x: 6, y: -3 }, - }); - }); - - cy.get(cesc("#\\/A3c")).should( - "contain.text", - `(${nInDOM(6)},${nInDOM(-3)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move A4"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/A4", - args: { x: -2, y: 7 }, - }); - }); - - cy.get(cesc("#\\/A4c")).should( - "contain.text", - `(${nInDOM(-2)},${nInDOM(7)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([-2, 7]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move B4"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/B4", - args: { x: -9, y: -8 }, - }); - }); - - cy.get(cesc("#\\/B4c")).should( - "contain.text", - `(${nInDOM(-9)},${nInDOM(-8)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([-2, 7]); - expect(stateVariables["/B4"].stateValues.xs).eqls([-9, -8]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move A5"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/gnolink/A", - args: { x: -10, y: -9 }, - }); - }); - - cy.get(cesc("#\\/A5c")).should( - "contain.text", - `(${nInDOM(-10)},${nInDOM(-9)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([-2, 7]); - expect(stateVariables["/B4"].stateValues.xs).eqls([-9, -8]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([-10, -9]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - -10, -9, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move B5"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/gnolink/B", - args: { x: -8, y: -7 }, - }); - }); - - cy.get(cesc("#\\/B5c")).should( - "contain.text", - `(${nInDOM(-8)},${nInDOM(-7)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([-2, 7]); - expect(stateVariables["/B4"].stateValues.xs).eqls([-9, -8]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([-10, -9]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([-8, -7]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - -10, -9, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - -8, -7, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move l3"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveLine", - componentName: "/gnolink/l", - args: { - point1coords: [6, 5], - point2coords: [4, -3], - }, - }); - }); - - cy.get(cesc("#\\/l3p1")).should( - "contain.text", - `(${nInDOM(6)},${nInDOM(5)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([-2, 7]); - expect(stateVariables["/B4"].stateValues.xs).eqls([-9, -8]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([6, 5]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([4, -3]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 6, 5, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 4, -3, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - }); - - it("copy points and lines with no link, with copySource", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - (1,2) - (3,4) - - - - - - - - - - - - - - - - - - - - -

- - - - - - - - - - - - -

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc(`#\\/Ax`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/l"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A2"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move A"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/A", - args: { x: -9, y: -3 }, - }); - }); - - cy.get(cesc("#\\/Ac")).should( - "contain.text", - `(${nInDOM(-9)},${nInDOM(-3)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-9, -3]); - expect(stateVariables["/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/l"].stateValues.point1).eqls([-9, -3]); - expect(stateVariables["/l"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A2"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move B"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/B", - args: { x: -2, y: 6 }, - }); - }); - - cy.get(cesc("#\\/Bc")).should( - "contain.text", - `(${nInDOM(-2)},${nInDOM(6)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-9, -3]); - expect(stateVariables["/B"].stateValues.xs).eqls([-2, 6]); - expect(stateVariables["/l"].stateValues.point1).eqls([-9, -3]); - expect(stateVariables["/l"].stateValues.point2).eqls([-2, 6]); - expect(stateVariables["/A2"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move l"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveLine", - componentName: "/l", - args: { - point1coords: [-7, -6], - point2coords: [8, 0], - }, - }); - }); - - cy.get(cesc("#\\/lp1")).should( - "contain.text", - `(${nInDOM(-7)},${nInDOM(-6)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move A2"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/A2", - args: { x: 5, y: 4 }, - }); - }); - - cy.get(cesc("#\\/A2c")).should( - "contain.text", - `(${nInDOM(5)},${nInDOM(4)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move l2"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveLine", - componentName: "/l2", - args: { - point1coords: [-5, 9], - point2coords: [-4, -1], - }, - }); - }); - - cy.get(cesc("#\\/l2p1")).should( - "contain.text", - `(${nInDOM(-5)},${nInDOM(9)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move A3"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/A3", - args: { x: 6, y: -3 }, - }); - }); - - cy.get(cesc("#\\/A3c")).should( - "contain.text", - `(${nInDOM(6)},${nInDOM(-3)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move A4"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/A4", - args: { x: -2, y: 7 }, - }); - }); - - cy.get(cesc("#\\/A4c")).should( - "contain.text", - `(${nInDOM(-2)},${nInDOM(7)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([-2, 7]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move B4"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/B4", - args: { x: -9, y: -8 }, - }); - }); - - cy.get(cesc("#\\/B4c")).should( - "contain.text", - `(${nInDOM(-9)},${nInDOM(-8)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([-2, 7]); - expect(stateVariables["/B4"].stateValues.xs).eqls([-9, -8]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move A5"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/gnolink/A", - args: { x: -10, y: -9 }, - }); - }); - - cy.get(cesc("#\\/A5c")).should( - "contain.text", - `(${nInDOM(-10)},${nInDOM(-9)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([-2, 7]); - expect(stateVariables["/B4"].stateValues.xs).eqls([-9, -8]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([-10, -9]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - -10, -9, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move B5"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/gnolink/B", - args: { x: -8, y: -7 }, - }); - }); - - cy.get(cesc("#\\/B5c")).should( - "contain.text", - `(${nInDOM(-8)},${nInDOM(-7)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([-2, 7]); - expect(stateVariables["/B4"].stateValues.xs).eqls([-9, -8]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([-10, -9]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([-8, -7]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - -10, -9, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - -8, -7, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move l3"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveLine", - componentName: "/gnolink/l", - args: { - point1coords: [6, 5], - point2coords: [4, -3], - }, - }); - }); - - cy.get(cesc("#\\/l3p1")).should( - "contain.text", - `(${nInDOM(6)},${nInDOM(5)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([-2, 7]); - expect(stateVariables["/B4"].stateValues.xs).eqls([-9, -8]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([6, 5]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([4, -3]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 6, 5, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 4, -3, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - }); - - it("copy points and lines with no link, with copySource, dot notation", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - (1,2) - (3,4) - - - - - - - - - - - - - - - - - - - - -

- - - - - - - - - - - - -

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc(`#\\/Ax`)) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/l"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A2"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move A"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/A", - args: { x: -9, y: -3 }, - }); - }); - - cy.get(cesc("#\\/Ac")).should( - "contain.text", - `(${nInDOM(-9)},${nInDOM(-3)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-9, -3]); - expect(stateVariables["/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/l"].stateValues.point1).eqls([-9, -3]); - expect(stateVariables["/l"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A2"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move B"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/B", - args: { x: -2, y: 6 }, - }); - }); - - cy.get(cesc("#\\/Bc")).should( - "contain.text", - `(${nInDOM(-2)},${nInDOM(6)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-9, -3]); - expect(stateVariables["/B"].stateValues.xs).eqls([-2, 6]); - expect(stateVariables["/l"].stateValues.point1).eqls([-9, -3]); - expect(stateVariables["/l"].stateValues.point2).eqls([-2, 6]); - expect(stateVariables["/A2"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move l"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveLine", - componentName: "/l", - args: { - point1coords: [-7, -6], - point2coords: [8, 0], - }, - }); - }); - - cy.get(cesc("#\\/lp1")).should( - "contain.text", - `(${nInDOM(-7)},${nInDOM(-6)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move A2"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/A2", - args: { x: 5, y: 4 }, - }); - }); - - cy.get(cesc("#\\/A2c")).should( - "contain.text", - `(${nInDOM(5)},${nInDOM(4)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([1, 2]); - expect(stateVariables["/l2"].stateValues.point2).eqls([3, 4]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move l2"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveLine", - componentName: "/l2", - args: { - point1coords: [-5, 9], - point2coords: [-4, -1], - }, - }); - }); - - cy.get(cesc("#\\/l2p1")).should( - "contain.text", - `(${nInDOM(-5)},${nInDOM(9)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move A3"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/A3", - args: { x: 6, y: -3 }, - }); - }); - - cy.get(cesc("#\\/A3c")).should( - "contain.text", - `(${nInDOM(6)},${nInDOM(-3)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move A4"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/A4", - args: { x: -2, y: 7 }, - }); - }); - - cy.get(cesc("#\\/A4c")).should( - "contain.text", - `(${nInDOM(-2)},${nInDOM(7)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([-2, 7]); - expect(stateVariables["/B4"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move B4"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/B4", - args: { x: -9, y: -8 }, - }); - }); - - cy.get(cesc("#\\/B4c")).should( - "contain.text", - `(${nInDOM(-9)},${nInDOM(-8)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([-2, 7]); - expect(stateVariables["/B4"].stateValues.xs).eqls([-9, -8]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 1, 2, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move A5"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/gnolink/A", - args: { x: -10, y: -9 }, - }); - }); - - cy.get(cesc("#\\/A5c")).should( - "contain.text", - `(${nInDOM(-10)},${nInDOM(-9)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([-2, 7]); - expect(stateVariables["/B4"].stateValues.xs).eqls([-9, -8]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([-10, -9]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - -10, -9, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 3, 4, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move B5"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/gnolink/B", - args: { x: -8, y: -7 }, - }); - }); - - cy.get(cesc("#\\/B5c")).should( - "contain.text", - `(${nInDOM(-8)},${nInDOM(-7)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([-2, 7]); - expect(stateVariables["/B4"].stateValues.xs).eqls([-9, -8]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([-10, -9]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([-8, -7]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - -10, -9, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - -8, -7, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - - cy.log("move l3"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveLine", - componentName: "/gnolink/l", - args: { - point1coords: [6, 5], - point2coords: [4, -3], - }, - }); - }); - - cy.get(cesc("#\\/l3p1")).should( - "contain.text", - `(${nInDOM(6)},${nInDOM(5)})`, - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([-7, -6]); - expect(stateVariables["/B"].stateValues.xs).eqls([8, 0]); - expect(stateVariables["/l"].stateValues.point1).eqls([-7, -6]); - expect(stateVariables["/l"].stateValues.point2).eqls([8, 0]); - expect(stateVariables["/A2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/l2"].stateValues.point1).eqls([-5, 9]); - expect(stateVariables["/l2"].stateValues.point2).eqls([-4, -1]); - expect(stateVariables["/A3"].stateValues.xs).eqls([6, -3]); - expect(stateVariables["/A4"].stateValues.xs).eqls([-2, 7]); - expect(stateVariables["/B4"].stateValues.xs).eqls([-9, -8]); - expect(stateVariables["/gnolink/A"].stateValues.xs).eqls([6, 5]); - expect(stateVariables["/gnolink/B"].stateValues.xs).eqls([4, -3]); - expect(stateVariables["/gnolink/l"].stateValues.point1).eqls([ - 6, 5, - ]); - expect(stateVariables["/gnolink/l"].stateValues.point2).eqls([ - 4, -3, - ]); - expect(stateVariables["/Ax"].stateValues.value).eqls(1); - }); - }); - - it("copy string with no link", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Hello

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/_p1")).should("have.text", "Hello"); - cy.get(cesc("#\\/p2")).should("have.text", "Hello"); - }); - - it("copy string with no link, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Hello

- $_p1{name="p2" link="false"} - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/_p1")).should("have.text", "Hello"); - cy.get(cesc("#\\/p2")).should("have.text", "Hello"); - }); - - it("copy string with no link, with copySource", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Hello

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/_p1")).should("have.text", "Hello"); - cy.get(cesc("#\\/p2")).should("have.text", "Hello"); - }); - - // This was causing a duplicate component name error - it("copy group with name inside with no link", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

hello

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/_p1")).should("have.text", "hello hello"); - cy.get(cesc("#\\/_p2")).should("have.text", "hello hello"); - }); - - // This was causing a duplicate component name error - it("copy group with name inside with no link, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

hello $m{name="q"}

-

$g{link="false"}

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/_p1")).should("have.text", "hello hello"); - cy.get(cesc("#\\/_p2")).should("have.text", "hello hello"); - }); - - // This was causing a duplicate component name error - it("copy group with assignNames inside with no link, with copySource", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

hello $m{name="q"}

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/_p1")).should("have.text", "hello hello"); - cy.get(cesc("#\\/_p2")).should("have.text", "hello hello"); - }); - - it("copy group with copies with no link", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

x+x

- - -
- - - - - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxc")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxd")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxe")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxf")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxg")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxh")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxi")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxj")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxk")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxl")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - }); - - it("copy group with copies with no link, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

x+x

- $twox{name="twoxa"} - $twox{name="twoxb"} -
- - - $twox{name="twoxc"} - $twox{link="false" name="twoxd"} - - $twoxa{name="twoxe"} - $twoxa{link="false" name="twoxf"} - - $twoxe{name="twoxg"} - $twoxf{link="false" name="twoxh"} - - $twoxb{name="twoxi"} - $twoxb{link="false" name="twoxj"} - - $twoxi{name="twoxk"} - $twoxj{link="false" name="twoxl"} - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxc")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxd")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxe")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxf")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxg")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxh")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxi")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxj")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxk")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxl")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - }); - - it("copy group with copies with no link, with copySource", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

x+x

- - -
- - - - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxb")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxc")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxd")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxe")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxf")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxg")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxh")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxi")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxj")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxk")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxl")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - }); - - it("copy group with copy overwriting attribute, no link", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - -

x+x - - x+x+x -

-
- - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - cy.get(cesc("#\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("3x"); - }); - - cy.get(cesc("#\\/g2\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g2\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - cy.get(cesc("#\\/g2\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("3x"); - }); - - cy.get(cesc("#\\/g3\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g3\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - cy.get(cesc("#\\/g3\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("3x"); - }); - - cy.log("change first simplify"); - cy.get(cesc("#\\/sim_input")).clear().type("none{enter}"); - - cy.get(cesc("#\\/twoxa")).should("contain.text", "x+x"); - cy.get(cesc("#\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x+x"); - }); - - cy.get(cesc("#\\/g2\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g2\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - cy.get(cesc("#\\/g2\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("3x"); - }); - - cy.get(cesc("#\\/g3\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g3\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - cy.get(cesc("#\\/g3\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("3x"); - }); - - cy.log("change second simplify"); - cy.get(cesc("#\\/g2\\/sim_input")).clear().type("none{enter}"); - - cy.get(cesc("#\\/g2\\/twoxa")).should("contain.text", "x+x"); - cy.get(cesc("#\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x+x"); - }); - - cy.get(cesc("#\\/g2\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g2\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g2\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x+x"); - }); - - cy.get(cesc("#\\/g3\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g3\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - cy.get(cesc("#\\/g3\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("3x"); - }); - - cy.log("change third simplify"); - cy.get(cesc("#\\/g3\\/sim_input")).clear().type("none{enter}"); - - cy.get(cesc("#\\/g3\\/twoxa")).should("contain.text", "x+x"); - cy.get(cesc("#\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x+x"); - }); - - cy.get(cesc("#\\/g2\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g2\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g2\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x+x"); - }); - - cy.get(cesc("#\\/g3\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g3\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g3\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x+x"); - }); - }); - - it("copy group with copy overwriting attribute, no link, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - -

x+x - $twox{simplify="$sim" name="twoxa"} - x+x+x -

-
- - $g{link="false" name="g2" newNamespace} - $g2{link="false" name="g3" newNamespace} - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - cy.get(cesc("#\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("3x"); - }); - - cy.get(cesc("#\\/g2\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g2\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - cy.get(cesc("#\\/g2\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("3x"); - }); - - cy.get(cesc("#\\/g3\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g3\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - cy.get(cesc("#\\/g3\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("3x"); - }); - - cy.log("change first simplify"); - cy.get(cesc("#\\/sim_input")).clear().type("none{enter}"); - - cy.get(cesc("#\\/twoxa")).should("contain.text", "x+x"); - cy.get(cesc("#\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x+x"); - }); - - cy.get(cesc("#\\/g2\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g2\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - cy.get(cesc("#\\/g2\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("3x"); - }); - - cy.get(cesc("#\\/g3\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g3\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - cy.get(cesc("#\\/g3\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("3x"); - }); - - cy.log("change second simplify"); - cy.get(cesc("#\\/g2\\/sim_input")).clear().type("none{enter}"); - - cy.get(cesc("#\\/g2\\/twoxa")).should("contain.text", "x+x"); - cy.get(cesc("#\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x+x"); - }); - - cy.get(cesc("#\\/g2\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g2\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g2\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x+x"); - }); - - cy.get(cesc("#\\/g3\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g3\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - cy.get(cesc("#\\/g3\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("3x"); - }); - - cy.log("change third simplify"); - cy.get(cesc("#\\/g3\\/sim_input")).clear().type("none{enter}"); - - cy.get(cesc("#\\/g3\\/twoxa")).should("contain.text", "x+x"); - cy.get(cesc("#\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x+x"); - }); - - cy.get(cesc("#\\/g2\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g2\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g2\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x+x"); - }); - - cy.get(cesc("#\\/g3\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g3\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g3\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x+x"); - }); - }); - - it("copy group with copy overwriting attribute, no link, with copySource", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - -

x+x - - x+x+x -

-
- - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - cy.get(cesc("#\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("3x"); - }); - - cy.get(cesc("#\\/g2\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g2\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - cy.get(cesc("#\\/g2\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("3x"); - }); - - cy.get(cesc("#\\/g3\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g3\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - cy.get(cesc("#\\/g3\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("3x"); - }); - - cy.log("change first simplify"); - cy.get(cesc("#\\/sim_input")).clear().type("none{enter}"); - - cy.get(cesc("#\\/twoxa")).should("contain.text", "x+x"); - cy.get(cesc("#\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x+x"); - }); - - cy.get(cesc("#\\/g2\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g2\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - cy.get(cesc("#\\/g2\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("3x"); - }); - - cy.get(cesc("#\\/g3\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g3\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - cy.get(cesc("#\\/g3\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("3x"); - }); - - cy.log("change second simplify"); - cy.get(cesc("#\\/g2\\/sim_input")).clear().type("none{enter}"); - - cy.get(cesc("#\\/g2\\/twoxa")).should("contain.text", "x+x"); - cy.get(cesc("#\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x+x"); - }); - - cy.get(cesc("#\\/g2\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g2\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g2\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x+x"); - }); - - cy.get(cesc("#\\/g3\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g3\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("2x"); - }); - cy.get(cesc("#\\/g3\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("3x"); - }); - - cy.log("change third simplify"); - cy.get(cesc("#\\/g3\\/sim_input")).clear().type("none{enter}"); - - cy.get(cesc("#\\/g3\\/twoxa")).should("contain.text", "x+x"); - cy.get(cesc("#\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x+x"); - }); - - cy.get(cesc("#\\/g2\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g2\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g2\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x+x"); - }); - - cy.get(cesc("#\\/g3\\/twox")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g3\\/twoxa")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x"); - }); - cy.get(cesc("#\\/g3\\/threex")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().replace(/−/g, "-")).equal("x+x+x"); - }); - }); - - it("copy group with link through name of external, no link", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

Credit achieved:

-
- - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinput1Anchor = - cesc2( - "#" + - stateVariables["/g/p/_answer1"].stateValues - .inputChildren[0].componentName, - ) + " textarea"; - let mathinput2Anchor = - cesc2( - "#" + - stateVariables["/g2/p/_answer1"].stateValues - .inputChildren[0].componentName, - ) + " textarea"; - - cy.get(cesc2("#/g/ca")).should("have.text", "0"); - cy.get(cesc2("#/g2/ca")).should("have.text", "0"); - - cy.get(mathinput1Anchor).type("2x{enter}", { force: true }); - - cy.get(cesc2("#/g/ca")).should("have.text", "1"); - cy.get(cesc2("#/g2/ca")).should("have.text", "0"); - - cy.get(mathinput2Anchor).type("2x{enter}", { force: true }); - - cy.get(cesc2("#/g/ca")).should("have.text", "1"); - cy.get(cesc2("#/g2/ca")).should("have.text", "1"); - }); - }); - - it("copy group with link through name of external, no link, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

Credit achieved: $(p/_answer1.creditAchieved{assignNames="ca"})

-
- - $g{link="false" name="g2"} - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinput1Anchor = - cesc2( - "#" + - stateVariables["/g/p/_answer1"].stateValues - .inputChildren[0].componentName, - ) + " textarea"; - let mathinput2Anchor = - cesc2( - "#" + - stateVariables["/g2/p/_answer1"].stateValues - .inputChildren[0].componentName, - ) + " textarea"; - - cy.get(cesc2("#/g/ca")).should("have.text", "0"); - cy.get(cesc2("#/g2/ca")).should("have.text", "0"); - - cy.get(mathinput1Anchor).type("2x{enter}", { force: true }); - - cy.get(cesc2("#/g/ca")).should("have.text", "1"); - cy.get(cesc2("#/g2/ca")).should("have.text", "0"); - - cy.get(mathinput2Anchor).type("2x{enter}", { force: true }); - - cy.get(cesc2("#/g/ca")).should("have.text", "1"); - cy.get(cesc2("#/g2/ca")).should("have.text", "1"); - }); - }); - - it("copy group with link through name of external, no link, with copySource", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

Credit achieved:

-
- - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathinput1Anchor = - cesc2( - "#" + - stateVariables["/g/p/_answer1"].stateValues - .inputChildren[0].componentName, - ) + " textarea"; - let mathinput2Anchor = - cesc2( - "#" + - stateVariables["/g2/p/_answer1"].stateValues - .inputChildren[0].componentName, - ) + " textarea"; - - cy.get(cesc2("#/g/ca")).should("have.text", "0"); - cy.get(cesc2("#/g2/ca")).should("have.text", "0"); - - cy.get(mathinput1Anchor).type("2x{enter}", { force: true }); - - cy.get(cesc2("#/g/ca")).should("have.text", "1"); - cy.get(cesc2("#/g2/ca")).should("have.text", "0"); - - cy.get(mathinput2Anchor).type("2x{enter}", { force: true }); - - cy.get(cesc2("#/g/ca")).should("have.text", "1"); - cy.get(cesc2("#/g2/ca")).should("have.text", "1"); - }); - }); - - it("copy group, no link, with function adapted to curve", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - x - - - - - `, - }, - "*", - ); - }); - - // just testing that page loads, i.e., that bug is removed so that don't get error - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - }); - - it("copy group, no link, with function adapted to curve, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - x - - - - $g{link="false"} - `, - }, - "*", - ); - }); - - // just testing that page loads, i.e., that bug is removed so that don't get error - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - }); - - it("copy group, no link, with function adapted to curve, with copySource", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - x - - - - - `, - }, - "*", - ); - }); - - // just testing that page loads, i.e., that bug is removed so that don't get error - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - }); - - it("copy group, no link, copy to external inside attribute", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - (a,b) - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/g/w")).should("have.text", "bye"); - cy.get(cesc2("#/g/Plabel")).should("have.text", "bye"); - cy.get(cesc2("#/g2/w")).should("have.text", "bye"); - cy.get(cesc2("#/g2/Plabel")).should("have.text", "bye"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g/P"].stateValues.label).eq("bye"); - expect(stateVariables["/g2/P"].stateValues.label).eq("bye"); - }); - - cy.get(cesc2("#/external_input")).clear().type("hi{enter}"); - - cy.get(cesc2("#/g/w")).should("have.text", "hi"); - cy.get(cesc2("#/g/Plabel")).should("have.text", "hi"); - cy.get(cesc2("#/g2/w")).should("have.text", "bye"); - cy.get(cesc2("#/g2/Plabel")).should("have.text", "bye"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g/P"].stateValues.label).eq("hi"); - expect(stateVariables["/g2/P"].stateValues.label).eq("bye"); - }); - }); - - it("copy group, no link, copy to external inside attribute, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - $(/external.value{assignNames="w"}) - (a,b) - $(P.label{assignNames="Plabel"}) - - - $g{name="g2" link="false"} - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/g/w")).should("have.text", "bye"); - cy.get(cesc2("#/g/Plabel")).should("have.text", "bye"); - cy.get(cesc2("#/g2/w")).should("have.text", "bye"); - cy.get(cesc2("#/g2/Plabel")).should("have.text", "bye"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g/P"].stateValues.label).eq("bye"); - expect(stateVariables["/g2/P"].stateValues.label).eq("bye"); - }); - - cy.get(cesc2("#/external_input")).clear().type("hi{enter}"); - - cy.get(cesc2("#/g/w")).should("have.text", "hi"); - cy.get(cesc2("#/g/Plabel")).should("have.text", "hi"); - cy.get(cesc2("#/g2/w")).should("have.text", "bye"); - cy.get(cesc2("#/g2/Plabel")).should("have.text", "bye"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g/P"].stateValues.label).eq("hi"); - expect(stateVariables["/g2/P"].stateValues.label).eq("bye"); - }); - }); - - it("copy group, no link, copy to external inside attribute, with copySource", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - (a,b) - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/g/w")).should("have.text", "bye"); - cy.get(cesc2("#/g/Plabel")).should("have.text", "bye"); - cy.get(cesc2("#/g2/w")).should("have.text", "bye"); - cy.get(cesc2("#/g2/Plabel")).should("have.text", "bye"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g/P"].stateValues.label).eq("bye"); - expect(stateVariables["/g2/P"].stateValues.label).eq("bye"); - }); - - cy.get(cesc2("#/external_input")).clear().type("hi{enter}"); - - cy.get(cesc2("#/g/w")).should("have.text", "hi"); - cy.get(cesc2("#/g/Plabel")).should("have.text", "hi"); - cy.get(cesc2("#/g2/w")).should("have.text", "bye"); - cy.get(cesc2("#/g2/Plabel")).should("have.text", "bye"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g/P"].stateValues.label).eq("hi"); - expect(stateVariables["/g2/P"].stateValues.label).eq("bye"); - }); - }); - - it("copy group, no link, internal copy to source alias is linked", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - $ti - - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/g/a/w")).should("have.text", "hello"); - cy.get(cesc2("#/g/a/Plabel")).should("have.text", "hello"); - cy.get(cesc2("#/g2/a/w")).should("have.text", "hello"); - cy.get(cesc2("#/g2/a/Plabel")).should("have.text", "hello"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g/a/P"].stateValues.label).eq("hello"); - expect(stateVariables["/g2/a/P"].stateValues.label).eq("hello"); - }); - - cy.get(cesc2("#/g/ti_input")).clear().type("one{enter}"); - cy.get(cesc2("#/g2/ti_input")).clear().type("two{enter}"); - - cy.get(cesc2("#/g/a/w")).should("have.text", "one"); - cy.get(cesc2("#/g/a/Plabel")).should("have.text", "one"); - cy.get(cesc2("#/g2/a/w")).should("have.text", "two"); - cy.get(cesc2("#/g2/a/Plabel")).should("have.text", "two"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g/a/P"].stateValues.label).eq("one"); - expect(stateVariables["/g2/a/P"].stateValues.label).eq("two"); - }); - }); - - it("copy group, no link, internal copy to source alias is linked, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - $ti - - - - - $g{name="g2" link="false"} - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/g/a/w")).should("have.text", "hello"); - cy.get(cesc2("#/g/a/Plabel")).should("have.text", "hello"); - cy.get(cesc2("#/g2/a/w")).should("have.text", "hello"); - cy.get(cesc2("#/g2/a/Plabel")).should("have.text", "hello"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g/a/P"].stateValues.label).eq("hello"); - expect(stateVariables["/g2/a/P"].stateValues.label).eq("hello"); - }); - - cy.get(cesc2("#/g/ti_input")).clear().type("one{enter}"); - cy.get(cesc2("#/g2/ti_input")).clear().type("two{enter}"); - - cy.get(cesc2("#/g/a/w")).should("have.text", "one"); - cy.get(cesc2("#/g/a/Plabel")).should("have.text", "one"); - cy.get(cesc2("#/g2/a/w")).should("have.text", "two"); - cy.get(cesc2("#/g2/a/Plabel")).should("have.text", "two"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g/a/P"].stateValues.label).eq("one"); - expect(stateVariables["/g2/a/P"].stateValues.label).eq("two"); - }); - }); - - it("copy group, no link, internal copy to source alias is linked, with copySource", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - $ti - - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/g/a/w")).should("have.text", "hello"); - cy.get(cesc2("#/g/a/Plabel")).should("have.text", "hello"); - cy.get(cesc2("#/g2/a/w")).should("have.text", "hello"); - cy.get(cesc2("#/g2/a/Plabel")).should("have.text", "hello"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g/a/P"].stateValues.label).eq("hello"); - expect(stateVariables["/g2/a/P"].stateValues.label).eq("hello"); - }); - - cy.get(cesc2("#/g/ti_input")).clear().type("one{enter}"); - cy.get(cesc2("#/g2/ti_input")).clear().type("two{enter}"); - - cy.get(cesc2("#/g/a/w")).should("have.text", "one"); - cy.get(cesc2("#/g/a/Plabel")).should("have.text", "one"); - cy.get(cesc2("#/g2/a/w")).should("have.text", "two"); - cy.get(cesc2("#/g2/a/Plabel")).should("have.text", "two"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g/a/P"].stateValues.label).eq("one"); - expect(stateVariables["/g2/a/P"].stateValues.label).eq("two"); - }); - }); - - it("copy no link containing external copies use absolute source", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - 2 - 2$n - - -

m =

-

m =

-
- - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/n")).should("have.text", "2"); - cy.get(cesc2("#/m")).should("have.text", "4"); - cy.get(cesc2("#/g/m1")).should("have.text", "4"); - cy.get(cesc2("#/g/m2")).should("have.text", "4"); - cy.get(cesc2("#/g2/m1")).should("have.text", "4"); - cy.get(cesc2("#/g2/m2")).should("have.text", "4"); - cy.get(cesc2("#/g3/m1")).should("have.text", "4"); - cy.get(cesc2("#/g3/m2")).should("have.text", "4"); - }); - - it("copy no link containing external copies use absolute source, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - 2 - 2$n - - -

m = $(../m{name="m1"})

-

m = $(../m{name="m2" link="false"})

-
- - $g{name="g2"} - $g{link="false" name="g3"} - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/n")).should("have.text", "2"); - cy.get(cesc2("#/m")).should("have.text", "4"); - cy.get(cesc2("#/g/m1")).should("have.text", "4"); - cy.get(cesc2("#/g/m2")).should("have.text", "4"); - cy.get(cesc2("#/g2/m1")).should("have.text", "4"); - cy.get(cesc2("#/g2/m2")).should("have.text", "4"); - cy.get(cesc2("#/g3/m1")).should("have.text", "4"); - cy.get(cesc2("#/g3/m2")).should("have.text", "4"); - }); - - it("copy no link containing external copies use absolute source, with copySource", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - 2 - 2$n - - -

m =

-

m =

-
- - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/n")).should("have.text", "2"); - cy.get(cesc2("#/m")).should("have.text", "4"); - cy.get(cesc2("#/g/m1")).should("have.text", "4"); - cy.get(cesc2("#/g/m2")).should("have.text", "4"); - cy.get(cesc2("#/g2/m1")).should("have.text", "4"); - cy.get(cesc2("#/g2/m2")).should("have.text", "4"); - cy.get(cesc2("#/g3/m1")).should("have.text", "4"); - cy.get(cesc2("#/g3/m2")).should("have.text", "4"); - }); - - it("copy dynamic map no link, check aliases", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -
- - 2 - - - - - - - - - - - - -
- -
- -
- -
- -
- - - -
- -
- -
- -
- - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/section1_title")).should("have.text", "Section 1"); - cy.get(cesc2("#/section1/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section1/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section1/p3")).should("not.exist"); - cy.get(cesc2("#/section1/p4")).should("not.exist"); - - cy.get(cesc2("#/section2_title")).should("have.text", "Section 2"); - cy.get(cesc2("#/section2/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section2/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section2/p3")).should("not.exist"); - cy.get(cesc2("#/section2/p4")).should("not.exist"); - - cy.get(cesc2("#/section3_title")).should("have.text", "Section 3"); - cy.get(cesc2("#/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3")).should("not.exist"); - cy.get(cesc2("#/p4")).should("not.exist"); - - cy.get(cesc2("#/section4_title")).should("have.text", "Section 4"); - cy.get(cesc2("#/section4/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section4/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section4/p3")).should("not.exist"); - cy.get(cesc2("#/section4/p4")).should("not.exist"); - - cy.get(cesc2("#/section5_title")).should("have.text", "Section 5"); - cy.get(cesc2("#/section5/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section5/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section5/p3")).should("not.exist"); - cy.get(cesc2("#/section5/p4")).should("not.exist"); - - cy.get(cesc2("#/section6_title")).should("have.text", "Section 6"); - cy.get(cesc2("#/p1a")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2a")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3a")).should("not.exist"); - cy.get(cesc2("#/p4a")).should("not.exist"); - - cy.get(cesc2("#/section7_title")).should("have.text", "Section 7"); - cy.get(cesc2("#/section7/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section7/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section7/p3")).should("not.exist"); - cy.get(cesc2("#/section7/p4")).should("not.exist"); - - cy.log("Add P via section 1"); - cy.get(cesc2("#/section1/addP_button")).click(); - - cy.get(cesc2("#/section1/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section1/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section1/p3")).should("have.text", "i=3, v=13"); - cy.get(cesc2("#/section1/p4")).should("not.exist"); - - cy.get(cesc2("#/section2/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section2/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section2/p3")).should("not.exist"); - cy.get(cesc2("#/section2/p4")).should("not.exist"); - - cy.get(cesc2("#/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3")).should("not.exist"); - cy.get(cesc2("#/p4")).should("not.exist"); - - cy.get(cesc2("#/section4/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section4/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section4/p3")).should("not.exist"); - cy.get(cesc2("#/section4/p4")).should("not.exist"); - - cy.get(cesc2("#/section5/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section5/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section5/p3")).should("have.text", "i=3, v=13"); - cy.get(cesc2("#/section5/p4")).should("not.exist"); - - cy.get(cesc2("#/p1a")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2a")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3a")).should("have.text", "i=3, v=13"); - cy.get(cesc2("#/p4a")).should("not.exist"); - - cy.get(cesc2("#/section7/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section7/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section7/p3")).should("have.text", "i=3, v=13"); - cy.get(cesc2("#/section7/p4")).should("not.exist"); - - cy.log("Remove P via section 7"); - cy.get(cesc2("#/section7/removeP_button")).click(); - - cy.get(cesc2("#/section1/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section1/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section1/p3")).should("not.exist"); - cy.get(cesc2("#/section1/p4")).should("not.exist"); - - cy.get(cesc2("#/section2/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section2/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section2/p3")).should("not.exist"); - cy.get(cesc2("#/section2/p4")).should("not.exist"); - - cy.get(cesc2("#/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3")).should("not.exist"); - cy.get(cesc2("#/p4")).should("not.exist"); - - cy.get(cesc2("#/section4/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section4/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section4/p3")).should("not.exist"); - cy.get(cesc2("#/section4/p4")).should("not.exist"); - - cy.get(cesc2("#/section5/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section5/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section5/p3")).should("not.exist"); - cy.get(cesc2("#/section5/p4")).should("not.exist"); - - cy.get(cesc2("#/p1a")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2a")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3a")).should("not.exist"); - cy.get(cesc2("#/p4a")).should("not.exist"); - - cy.get(cesc2("#/section7/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section7/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section7/p3")).should("not.exist"); - cy.get(cesc2("#/section7/p4")).should("not.exist"); - - cy.log("Add P via section 4"); - cy.get(cesc2("#/section4/addP_button")).click(); - - cy.get(cesc2("#/section1/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section1/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section1/p3")).should("not.exist"); - cy.get(cesc2("#/section1/p4")).should("not.exist"); - - cy.get(cesc2("#/section2/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section2/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section2/p3")).should("not.exist"); - cy.get(cesc2("#/section2/p4")).should("not.exist"); - - cy.get(cesc2("#/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3")).should("not.exist"); - cy.get(cesc2("#/p4")).should("not.exist"); - - cy.get(cesc2("#/section4/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section4/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section4/p3")).should("have.text", "i=3, v=13"); - cy.get(cesc2("#/section4/p4")).should("not.exist"); - - cy.get(cesc2("#/section5/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section5/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section5/p3")).should("not.exist"); - cy.get(cesc2("#/section5/p4")).should("not.exist"); - - cy.get(cesc2("#/p1a")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2a")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3a")).should("not.exist"); - cy.get(cesc2("#/p4a")).should("not.exist"); - - cy.get(cesc2("#/section7/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section7/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section7/p3")).should("not.exist"); - cy.get(cesc2("#/section7/p4")).should("not.exist"); - - cy.log("Remove P via section 4"); - cy.get(cesc2("#/section4/removeP_button")).click(); - - cy.get(cesc2("#/section1/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section1/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section1/p3")).should("not.exist"); - cy.get(cesc2("#/section1/p4")).should("not.exist"); - - cy.get(cesc2("#/section2/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section2/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section2/p3")).should("not.exist"); - cy.get(cesc2("#/section2/p4")).should("not.exist"); - - cy.get(cesc2("#/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3")).should("not.exist"); - cy.get(cesc2("#/p4")).should("not.exist"); - - cy.get(cesc2("#/section4/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section4/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section4/p3")).should("not.exist"); - cy.get(cesc2("#/section4/p4")).should("not.exist"); - - cy.get(cesc2("#/section5/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section5/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section5/p3")).should("not.exist"); - cy.get(cesc2("#/section5/p4")).should("not.exist"); - - cy.get(cesc2("#/p1a")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2a")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3a")).should("not.exist"); - cy.get(cesc2("#/p4a")).should("not.exist"); - - cy.get(cesc2("#/section7/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section7/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section7/p3")).should("not.exist"); - cy.get(cesc2("#/section7/p4")).should("not.exist"); - }); - - it("copy dynamic map no link, check aliases", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -
- - 2 - - - - - - - - - - - - -
- -
- $(../section1/_map1{link='false' assignNames='(p1) (p2) (p3) (p4)'}) -
- -
- $(section1/_map1{link='false' assignNames='(p1) (p2) (p3) (p4)'}) -
- - $section1{link='false' name="section4"} - -
- $(../section1/_map1{assignNames='(p1) (p2) (p3) (p4)'}) -
- -
- $(section1/_map1{assignNames='(p1a) (p2a) (p3a) (p4a)'}) -
- - $section1{name="section7"} - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/section1_title")).should("have.text", "Section 1"); - cy.get(cesc2("#/section1/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section1/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section1/p3")).should("not.exist"); - cy.get(cesc2("#/section1/p4")).should("not.exist"); - - cy.get(cesc2("#/section2_title")).should("have.text", "Section 2"); - cy.get(cesc2("#/section2/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section2/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section2/p3")).should("not.exist"); - cy.get(cesc2("#/section2/p4")).should("not.exist"); - - cy.get(cesc2("#/section3_title")).should("have.text", "Section 3"); - cy.get(cesc2("#/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3")).should("not.exist"); - cy.get(cesc2("#/p4")).should("not.exist"); - - cy.get(cesc2("#/section4_title")).should("have.text", "Section 4"); - cy.get(cesc2("#/section4/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section4/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section4/p3")).should("not.exist"); - cy.get(cesc2("#/section4/p4")).should("not.exist"); - - cy.get(cesc2("#/section5_title")).should("have.text", "Section 5"); - cy.get(cesc2("#/section5/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section5/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section5/p3")).should("not.exist"); - cy.get(cesc2("#/section5/p4")).should("not.exist"); - - cy.get(cesc2("#/section6_title")).should("have.text", "Section 6"); - cy.get(cesc2("#/p1a")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2a")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3a")).should("not.exist"); - cy.get(cesc2("#/p4a")).should("not.exist"); - - cy.get(cesc2("#/section7_title")).should("have.text", "Section 7"); - cy.get(cesc2("#/section7/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section7/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section7/p3")).should("not.exist"); - cy.get(cesc2("#/section7/p4")).should("not.exist"); - - cy.get(cesc2("#/section1/addP_button")).click(); - - cy.get(cesc2("#/section1/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section1/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section1/p3")).should("have.text", "i=3, v=13"); - cy.get(cesc2("#/section1/p4")).should("not.exist"); - - cy.get(cesc2("#/section2/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section2/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section2/p3")).should("not.exist"); - cy.get(cesc2("#/section2/p4")).should("not.exist"); - - cy.get(cesc2("#/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3")).should("not.exist"); - cy.get(cesc2("#/p4")).should("not.exist"); - - cy.get(cesc2("#/section4/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section4/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section4/p3")).should("not.exist"); - cy.get(cesc2("#/section4/p4")).should("not.exist"); - - cy.get(cesc2("#/section5/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section5/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section5/p3")).should("have.text", "i=3, v=13"); - cy.get(cesc2("#/section5/p4")).should("not.exist"); - - cy.get(cesc2("#/p1a")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2a")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3a")).should("have.text", "i=3, v=13"); - cy.get(cesc2("#/p4a")).should("not.exist"); - - cy.get(cesc2("#/section7/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section7/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section7/p3")).should("have.text", "i=3, v=13"); - cy.get(cesc2("#/section7/p4")).should("not.exist"); - - cy.get(cesc2("#/section7/removeP_button")).click(); - - cy.get(cesc2("#/section1/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section1/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section1/p3")).should("not.exist"); - cy.get(cesc2("#/section1/p4")).should("not.exist"); - - cy.get(cesc2("#/section2/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section2/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section2/p3")).should("not.exist"); - cy.get(cesc2("#/section2/p4")).should("not.exist"); - - cy.get(cesc2("#/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3")).should("not.exist"); - cy.get(cesc2("#/p4")).should("not.exist"); - - cy.get(cesc2("#/section4/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section4/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section4/p3")).should("not.exist"); - cy.get(cesc2("#/section4/p4")).should("not.exist"); - - cy.get(cesc2("#/section5/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section5/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section5/p3")).should("not.exist"); - cy.get(cesc2("#/section5/p4")).should("not.exist"); - - cy.get(cesc2("#/p1a")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2a")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3a")).should("not.exist"); - cy.get(cesc2("#/p4a")).should("not.exist"); - - cy.get(cesc2("#/section7/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section7/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section7/p3")).should("not.exist"); - cy.get(cesc2("#/section7/p4")).should("not.exist"); - - cy.get(cesc2("#/section4/addP_button")).click(); - - cy.get(cesc2("#/section1/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section1/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section1/p3")).should("not.exist"); - cy.get(cesc2("#/section1/p4")).should("not.exist"); - - cy.get(cesc2("#/section2/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section2/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section2/p3")).should("not.exist"); - cy.get(cesc2("#/section2/p4")).should("not.exist"); - - cy.get(cesc2("#/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3")).should("not.exist"); - cy.get(cesc2("#/p4")).should("not.exist"); - - cy.get(cesc2("#/section4/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section4/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section4/p3")).should("have.text", "i=3, v=13"); - cy.get(cesc2("#/section4/p4")).should("not.exist"); - - cy.get(cesc2("#/section5/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section5/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section5/p3")).should("not.exist"); - cy.get(cesc2("#/section5/p4")).should("not.exist"); - - cy.get(cesc2("#/p1a")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2a")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3a")).should("not.exist"); - cy.get(cesc2("#/p4a")).should("not.exist"); - - cy.get(cesc2("#/section7/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section7/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section7/p3")).should("not.exist"); - cy.get(cesc2("#/section7/p4")).should("not.exist"); - - cy.get(cesc2("#/section4/removeP_button")).click(); - - cy.get(cesc2("#/section1/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section1/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section1/p3")).should("not.exist"); - cy.get(cesc2("#/section1/p4")).should("not.exist"); - - cy.get(cesc2("#/section2/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section2/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section2/p3")).should("not.exist"); - cy.get(cesc2("#/section2/p4")).should("not.exist"); - - cy.get(cesc2("#/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3")).should("not.exist"); - cy.get(cesc2("#/p4")).should("not.exist"); - - cy.get(cesc2("#/section4/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section4/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section4/p3")).should("not.exist"); - cy.get(cesc2("#/section4/p4")).should("not.exist"); - - cy.get(cesc2("#/section5/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section5/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section5/p3")).should("not.exist"); - cy.get(cesc2("#/section5/p4")).should("not.exist"); - - cy.get(cesc2("#/p1a")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2a")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3a")).should("not.exist"); - cy.get(cesc2("#/p4a")).should("not.exist"); - - cy.get(cesc2("#/section7/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section7/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section7/p3")).should("not.exist"); - cy.get(cesc2("#/section7/p4")).should("not.exist"); - }); - - it("copy dynamic map no link, check aliases, with copySource", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -
- - 2 - - - - - - - - - - - - -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -
- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/section1_title")).should("have.text", "Section 1"); - cy.get(cesc2("#/section1/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section1/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section1/p3")).should("not.exist"); - cy.get(cesc2("#/section1/p4")).should("not.exist"); - - cy.get(cesc2("#/section2_title")).should("have.text", "Section 2"); - cy.get(cesc2("#/section2/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section2/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section2/p3")).should("not.exist"); - cy.get(cesc2("#/section2/p4")).should("not.exist"); - - cy.get(cesc2("#/section3_title")).should("have.text", "Section 3"); - cy.get(cesc2("#/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3")).should("not.exist"); - cy.get(cesc2("#/p4")).should("not.exist"); - - cy.get(cesc2("#/section4_title")).should("have.text", "Section 4"); - cy.get(cesc2("#/section4/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section4/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section4/p3")).should("not.exist"); - cy.get(cesc2("#/section4/p4")).should("not.exist"); - - cy.get(cesc2("#/section5_title")).should("have.text", "Section 5"); - cy.get(cesc2("#/section5/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section5/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section5/p3")).should("not.exist"); - cy.get(cesc2("#/section5/p4")).should("not.exist"); - - cy.get(cesc2("#/section6_title")).should("have.text", "Section 6"); - cy.get(cesc2("#/p1a")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2a")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3a")).should("not.exist"); - cy.get(cesc2("#/p4a")).should("not.exist"); - - cy.get(cesc2("#/section7_title")).should("have.text", "Section 7"); - cy.get(cesc2("#/section7/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section7/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section7/p3")).should("not.exist"); - cy.get(cesc2("#/section7/p4")).should("not.exist"); - - cy.get(cesc2("#/section1/addP_button")).click(); - - cy.get(cesc2("#/section1/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section1/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section1/p3")).should("have.text", "i=3, v=13"); - cy.get(cesc2("#/section1/p4")).should("not.exist"); - - cy.get(cesc2("#/section2/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section2/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section2/p3")).should("not.exist"); - cy.get(cesc2("#/section2/p4")).should("not.exist"); - - cy.get(cesc2("#/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3")).should("not.exist"); - cy.get(cesc2("#/p4")).should("not.exist"); - - cy.get(cesc2("#/section4/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section4/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section4/p3")).should("not.exist"); - cy.get(cesc2("#/section4/p4")).should("not.exist"); - - cy.get(cesc2("#/section5/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section5/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section5/p3")).should("have.text", "i=3, v=13"); - cy.get(cesc2("#/section5/p4")).should("not.exist"); - - cy.get(cesc2("#/p1a")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2a")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3a")).should("have.text", "i=3, v=13"); - cy.get(cesc2("#/p4a")).should("not.exist"); - - cy.get(cesc2("#/section7/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section7/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section7/p3")).should("have.text", "i=3, v=13"); - cy.get(cesc2("#/section7/p4")).should("not.exist"); - - cy.get(cesc2("#/section7/removeP_button")).click(); - - cy.get(cesc2("#/section1/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section1/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section1/p3")).should("not.exist"); - cy.get(cesc2("#/section1/p4")).should("not.exist"); - - cy.get(cesc2("#/section2/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section2/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section2/p3")).should("not.exist"); - cy.get(cesc2("#/section2/p4")).should("not.exist"); - - cy.get(cesc2("#/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3")).should("not.exist"); - cy.get(cesc2("#/p4")).should("not.exist"); - - cy.get(cesc2("#/section4/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section4/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section4/p3")).should("not.exist"); - cy.get(cesc2("#/section4/p4")).should("not.exist"); - - cy.get(cesc2("#/section5/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section5/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section5/p3")).should("not.exist"); - cy.get(cesc2("#/section5/p4")).should("not.exist"); - - cy.get(cesc2("#/p1a")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2a")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3a")).should("not.exist"); - cy.get(cesc2("#/p4a")).should("not.exist"); - - cy.get(cesc2("#/section7/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section7/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section7/p3")).should("not.exist"); - cy.get(cesc2("#/section7/p4")).should("not.exist"); - - cy.get(cesc2("#/section4/addP_button")).click(); - - cy.get(cesc2("#/section1/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section1/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section1/p3")).should("not.exist"); - cy.get(cesc2("#/section1/p4")).should("not.exist"); - - cy.get(cesc2("#/section2/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section2/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section2/p3")).should("not.exist"); - cy.get(cesc2("#/section2/p4")).should("not.exist"); - - cy.get(cesc2("#/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3")).should("not.exist"); - cy.get(cesc2("#/p4")).should("not.exist"); - - cy.get(cesc2("#/section4/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section4/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section4/p3")).should("have.text", "i=3, v=13"); - cy.get(cesc2("#/section4/p4")).should("not.exist"); - - cy.get(cesc2("#/section5/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section5/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section5/p3")).should("not.exist"); - cy.get(cesc2("#/section5/p4")).should("not.exist"); - - cy.get(cesc2("#/p1a")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2a")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3a")).should("not.exist"); - cy.get(cesc2("#/p4a")).should("not.exist"); - - cy.get(cesc2("#/section7/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section7/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section7/p3")).should("not.exist"); - cy.get(cesc2("#/section7/p4")).should("not.exist"); - - cy.get(cesc2("#/section4/removeP_button")).click(); - - cy.get(cesc2("#/section1/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section1/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section1/p3")).should("not.exist"); - cy.get(cesc2("#/section1/p4")).should("not.exist"); - - cy.get(cesc2("#/section2/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section2/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section2/p3")).should("not.exist"); - cy.get(cesc2("#/section2/p4")).should("not.exist"); - - cy.get(cesc2("#/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3")).should("not.exist"); - cy.get(cesc2("#/p4")).should("not.exist"); - - cy.get(cesc2("#/section4/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section4/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section4/p3")).should("not.exist"); - cy.get(cesc2("#/section4/p4")).should("not.exist"); - - cy.get(cesc2("#/section5/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section5/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section5/p3")).should("not.exist"); - cy.get(cesc2("#/section5/p4")).should("not.exist"); - - cy.get(cesc2("#/p1a")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/p2a")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/p3a")).should("not.exist"); - cy.get(cesc2("#/p4a")).should("not.exist"); - - cy.get(cesc2("#/section7/p1")).should("have.text", "i=1, v=11"); - cy.get(cesc2("#/section7/p2")).should("have.text", "i=2, v=12"); - cy.get(cesc2("#/section7/p3")).should("not.exist"); - cy.get(cesc2("#/section7/p4")).should("not.exist"); - }); - - it("copy map source with no link", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Number of iterations:

- - - - - - - - - - - -

A:

-

B:

-

C:

-

D:

-

E:

-

F:

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/A2")).should("not.exist"); - cy.get(cesc2("#/B2")).should("not.exist"); - cy.get(cesc2("#/C2")).should("not.exist"); - cy.get(cesc2("#/D2")).should("not.exist"); - cy.get(cesc2("#/E2")).should("not.exist"); - cy.get(cesc2("#/F2")).should("not.exist"); - - cy.get(cesc("#\\/n") + " textarea").type("1{enter}", { force: true }); - - cy.get(cesc2("#/A2") + " .mjx-mrow").should("contain.text", "(1,2)"); - cy.get(cesc2("#/A2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc2("#/B2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,4)"); - cy.get(cesc2("#/C2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(5,6)"); - cy.get(cesc2("#/D2")).should("not.exist"); - cy.get(cesc2("#/E2")).should("not.exist"); - cy.get(cesc2("#/F2")).should("not.exist"); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/A", - args: { x: 9, y: 0 }, - }); - win.callAction1({ - actionName: "movePoint", - componentName: "/B", - args: { x: 1, y: 8 }, - }); - win.callAction1({ - actionName: "movePoint", - componentName: "/C", - args: { x: 7, y: 2 }, - }); - }); - - cy.get(cesc2("#/C2") + " .mjx-mrow").should("contain.text", "(7,2)"); - cy.get(cesc2("#/A2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(9,0)"); - cy.get(cesc2("#/B2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,8)"); - cy.get(cesc2("#/C2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,2)"); - cy.get(cesc2("#/D2")).should("not.exist"); - cy.get(cesc2("#/E2")).should("not.exist"); - cy.get(cesc2("#/F2")).should("not.exist"); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - - cy.get(cesc2("#/D2") + " .mjx-mrow").should("contain.text", "(2,3)"); - cy.get(cesc2("#/A2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(9,0)"); - cy.get(cesc2("#/B2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,8)"); - cy.get(cesc2("#/C2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,2)"); - cy.get(cesc2("#/D2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2,3)"); - cy.get(cesc2("#/E2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(4,5)"); - cy.get(cesc2("#/F2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(6,7)"); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/D", - args: { x: 0, y: 10 }, - }); - win.callAction1({ - actionName: "movePoint", - componentName: "/E", - args: { x: 9, y: 1 }, - }); - win.callAction1({ - actionName: "movePoint", - componentName: "/F", - args: { x: 2, y: 8 }, - }); - }); - - cy.get(cesc2("#/F2") + " .mjx-mrow").should("contain.text", "(2,8)"); - cy.get(cesc2("#/A2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(9,0)"); - cy.get(cesc2("#/B2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,8)"); - cy.get(cesc2("#/C2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,2)"); - cy.get(cesc2("#/D2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,10)"); - cy.get(cesc2("#/E2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(9,1)"); - cy.get(cesc2("#/F2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2,8)"); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}0{enter}", { - force: true, - }); - - cy.get(cesc2("#/A2")).should("not.exist"); - cy.get(cesc2("#/B2")).should("not.exist"); - cy.get(cesc2("#/C2")).should("not.exist"); - cy.get(cesc2("#/D2")).should("not.exist"); - cy.get(cesc2("#/E2")).should("not.exist"); - cy.get(cesc2("#/F2")).should("not.exist"); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - - cy.get(cesc2("#/F2") + " .mjx-mrow").should("contain.text", "(2,8)"); - cy.get(cesc2("#/A2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(9,0)"); - cy.get(cesc2("#/B2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,8)"); - cy.get(cesc2("#/C2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,2)"); - cy.get(cesc2("#/D2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,10)"); - cy.get(cesc2("#/E2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(9,1)"); - cy.get(cesc2("#/F2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2,8)"); - }); - - it("copy map source with no link, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Number of iterations:

- - - - - - - - - - - -

A: $A{name="A2"}

-

B: $B{name="B2"}

-

C: $C{name="C2"}

-

D: $D{name="D2"}

-

E: $E{name="E2"}

-

F: $F{name="F2"}

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/A2")).should("not.exist"); - cy.get(cesc2("#/B2")).should("not.exist"); - cy.get(cesc2("#/C2")).should("not.exist"); - cy.get(cesc2("#/D2")).should("not.exist"); - cy.get(cesc2("#/E2")).should("not.exist"); - cy.get(cesc2("#/F2")).should("not.exist"); - - cy.get(cesc("#\\/n") + " textarea").type("1{enter}", { force: true }); - - cy.get(cesc2("#/A2") + " .mjx-mrow").should("contain.text", "(1,2)"); - cy.get(cesc2("#/A2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc2("#/B2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,4)"); - cy.get(cesc2("#/C2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(5,6)"); - cy.get(cesc2("#/D2")).should("not.exist"); - cy.get(cesc2("#/E2")).should("not.exist"); - cy.get(cesc2("#/F2")).should("not.exist"); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/A", - args: { x: 9, y: 0 }, - }); - win.callAction1({ - actionName: "movePoint", - componentName: "/B", - args: { x: 1, y: 8 }, - }); - win.callAction1({ - actionName: "movePoint", - componentName: "/C", - args: { x: 7, y: 2 }, - }); - }); - - cy.get(cesc2("#/C2") + " .mjx-mrow").should("contain.text", "(7,2)"); - cy.get(cesc2("#/A2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(9,0)"); - cy.get(cesc2("#/B2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,8)"); - cy.get(cesc2("#/C2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,2)"); - cy.get(cesc2("#/D2")).should("not.exist"); - cy.get(cesc2("#/E2")).should("not.exist"); - cy.get(cesc2("#/F2")).should("not.exist"); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - - cy.get(cesc2("#/D2") + " .mjx-mrow").should("contain.text", "(2,3)"); - cy.get(cesc2("#/A2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(9,0)"); - cy.get(cesc2("#/B2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,8)"); - cy.get(cesc2("#/C2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,2)"); - cy.get(cesc2("#/D2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2,3)"); - cy.get(cesc2("#/E2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(4,5)"); - cy.get(cesc2("#/F2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(6,7)"); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/D", - args: { x: 0, y: 10 }, - }); - win.callAction1({ - actionName: "movePoint", - componentName: "/E", - args: { x: 9, y: 1 }, - }); - win.callAction1({ - actionName: "movePoint", - componentName: "/F", - args: { x: 2, y: 8 }, - }); - }); - - cy.get(cesc2("#/F2") + " .mjx-mrow").should("contain.text", "(2,8)"); - cy.get(cesc2("#/A2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(9,0)"); - cy.get(cesc2("#/B2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,8)"); - cy.get(cesc2("#/C2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,2)"); - cy.get(cesc2("#/D2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,10)"); - cy.get(cesc2("#/E2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(9,1)"); - cy.get(cesc2("#/F2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2,8)"); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}0{enter}", { - force: true, - }); - - cy.get(cesc2("#/A2")).should("not.exist"); - cy.get(cesc2("#/B2")).should("not.exist"); - cy.get(cesc2("#/C2")).should("not.exist"); - cy.get(cesc2("#/D2")).should("not.exist"); - cy.get(cesc2("#/E2")).should("not.exist"); - cy.get(cesc2("#/F2")).should("not.exist"); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - - cy.get(cesc2("#/F2") + " .mjx-mrow").should("contain.text", "(2,8)"); - cy.get(cesc2("#/A2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(9,0)"); - cy.get(cesc2("#/B2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,8)"); - cy.get(cesc2("#/C2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,2)"); - cy.get(cesc2("#/D2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,10)"); - cy.get(cesc2("#/E2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(9,1)"); - cy.get(cesc2("#/F2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2,8)"); - }); - - it("copy no-link of a copy prop", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - x - - - - $xval - $xvalnl - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/x") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/xval") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/xvalnl") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - - cy.get(cesc2("#/mi1") + " textarea").type("{end}{backspace}y{enter}", { - force: true, - }); - - cy.get(cesc2("#/x") + " .mjx-mrow").should("contain.text", "y"); - cy.get(cesc2("#/x") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/xval") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/xvalnl") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - - cy.get(cesc2("#/mi2") + " textarea").type("{end}{backspace}z{enter}", { - force: true, - }); - - cy.get(cesc2("#/xvalnl") + " .mjx-mrow").should("contain.text", "z"); - cy.get(cesc2("#/xvalnl") + " .mjx-mrow") - .eq(0) - .should("have.text", "z"); - - cy.get(cesc2("#/x") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/xval") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - }); - - it("copy no-link of a copy prop 2", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - - - - - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/v1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,1)"); - cy.get(cesc2("#/v1nla") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,1)"); - cy.get(cesc2("#/v2nla") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,1)"); - cy.get(cesc2("#/v3nla") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,1)"); - - cy.log("Move v1"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/v1", - args: { x: 2, y: 3 }, - }); - }); - - cy.get(cesc2("#/v1a") + " .mjx-mrow").should("contain.text", "(2,3)"); - cy.get(cesc2("#/v1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2,3)"); - cy.get(cesc2("#/v1nla") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,1)"); - cy.get(cesc2("#/v2nla") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,1)"); - cy.get(cesc2("#/v3nla") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,1)"); - - cy.log("Move v1nl"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/v1nl", - args: { x: 3, y: 4 }, - }); - }); - - cy.get(cesc2("#/v1nla") + " .mjx-mrow").should("contain.text", "(3,4)"); - cy.get(cesc2("#/v1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2,3)"); - cy.get(cesc2("#/v1nla") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,4)"); - cy.get(cesc2("#/v2nla") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,1)"); - cy.get(cesc2("#/v3nla") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,1)"); - - cy.log("Move v2nl"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/v2nl", - args: { x: 4, y: 5 }, - }); - }); - - cy.get(cesc2("#/v2nla") + " .mjx-mrow").should("contain.text", "(4,5)"); - cy.get(cesc2("#/v1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2,3)"); - cy.get(cesc2("#/v1nla") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,4)"); - cy.get(cesc2("#/v2nla") + " .mjx-mrow") - .eq(0) - .should("have.text", "(4,5)"); - cy.get(cesc2("#/v3nla") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,1)"); - - cy.log("Move v3nl"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/v3nl", - args: { x: 5, y: 6 }, - }); - }); - - cy.get(cesc2("#/v3nla") + " .mjx-mrow").should("contain.text", "(5,6)"); - cy.get(cesc2("#/v1a") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2,3)"); - cy.get(cesc2("#/v1nla") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,4)"); - cy.get(cesc2("#/v2nla") + " .mjx-mrow") - .eq(0) - .should("have.text", "(4,5)"); - cy.get(cesc2("#/v3nla") + " .mjx-mrow") - .eq(0) - .should("have.text", "(5,6)"); - }); - - it("external content cannot reach outside namespace", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

Don't get this: Bye

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/hi")).should("have.text", "Bye"); - - cy.get(cesc2("#/greetings/hi")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/c1")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/c2")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/c3")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/c4")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/c5")).should("have.text", "Hello"); - - cy.get(cesc2("#/greetings/s/hi")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/l1")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/c1")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/c2")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/c3")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/c4")).should("have.text", "Hello"); - - cy.get(cesc2("#/greetings/s/s/hi")).should("have.text", "Marhaban"); - cy.get(cesc2("#/greetings/s/s/l1")).should("have.text", "Marhaban"); - cy.get(cesc2("#/greetings/s/s/m1")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/s/c1")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/s/c2")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/s/c3")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/s/c4")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/s/c5")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/s/c5")).should("have.text", "Hello"); - }); - - it("external content cannot reach outside namespace, external is single section", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

Don't get this: Bye

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/hi")).should("have.text", "Bye"); - - cy.get(cesc2("#/greetings/hi")).should("have.text", "Hello"); - - cy.get(cesc2("#/greetings/c1")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/c2")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/c3")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/c4")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/c5")).should("have.text", "Hello"); - - cy.get(cesc2("#/greetings/s/hi")).should("have.text", "Hola"); - - cy.get(cesc2("#/greetings/s/l1")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/l2")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/l3")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/l4")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/l5")).should("have.text", "Hola"); - - cy.get(cesc2("#/greetings/s/c1")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/c2")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/c3")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/c4")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/c5")).should("have.text", "Hello"); - - cy.get(cesc2("#/greetings/s/s/hi")).should("have.text", "Marhaban"); - - cy.get(cesc2("#/greetings/s/s/l1")).should("have.text", "Marhaban"); - cy.get(cesc2("#/greetings/s/s/l2")).should("have.text", "Marhaban"); - cy.get(cesc2("#/greetings/s/s/l3")).should("have.text", "Marhaban"); - cy.get(cesc2("#/greetings/s/s/l4")).should("have.text", "Marhaban"); - cy.get(cesc2("#/greetings/s/s/l5")).should("have.text", "Marhaban"); - - cy.get(cesc2("#/greetings/s/s/m1")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/s/m2")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/s/m3")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/s/m4")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/s/m5")).should("have.text", "Hola"); - - cy.get(cesc2("#/greetings/s/s/c1")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/s/c2")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/s/c3")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/s/c4")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/s/c5")).should("have.text", "Hello"); - }); - - it("external content cannot reach outside namespace, with copyFromURI", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -
- -

Don't get this: Bye

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/hi")).should("have.text", "Bye"); - - cy.get(cesc2("#/greetings/hi")).should("have.text", "Hello"); - - cy.get(cesc2("#/greetings/c1")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/c2")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/c3")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/c4")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/c5")).should("have.text", "Hello"); - - cy.get(cesc2("#/greetings/s/hi")).should("have.text", "Hola"); - - cy.get(cesc2("#/greetings/s/l1")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/l2")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/l3")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/l4")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/l5")).should("have.text", "Hola"); - - cy.get(cesc2("#/greetings/s/c1")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/c2")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/c3")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/c4")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/c5")).should("have.text", "Hello"); - - cy.get(cesc2("#/greetings/s/s/hi")).should("have.text", "Marhaban"); - - cy.get(cesc2("#/greetings/s/s/l1")).should("have.text", "Marhaban"); - cy.get(cesc2("#/greetings/s/s/l2")).should("have.text", "Marhaban"); - cy.get(cesc2("#/greetings/s/s/l3")).should("have.text", "Marhaban"); - cy.get(cesc2("#/greetings/s/s/l4")).should("have.text", "Marhaban"); - cy.get(cesc2("#/greetings/s/s/l5")).should("have.text", "Marhaban"); - - cy.get(cesc2("#/greetings/s/s/m1")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/s/m2")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/s/m3")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/s/m4")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/s/m5")).should("have.text", "Hola"); - - cy.get(cesc2("#/greetings/s/s/c1")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/s/c2")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/s/c3")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/s/c4")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/s/c5")).should("have.text", "Hello"); - }); - - it("external content cannot reach outside namespace, external has namespace", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

Don't get this: Bye

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/hi")).should("have.text", "Bye"); - - cy.get(cesc2("#/greetings/hi")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/c1")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/c2")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/c3")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/c4")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/c5")).should("have.text", "Hello"); - - cy.get(cesc2("#/greetings/nm1")).should("not.exist"); - cy.get(cesc2("#/greetings/nm2")).should("not.exist"); - cy.get(cesc2("#/greetings/nm3")).should("not.exist"); - cy.get(cesc2("#/greetings/nm4")).should("not.exist"); - - cy.get(cesc2("#/greetings/pNoMatch")).should( - "have.text", - "Four no matches:", - ); - - cy.get(cesc2("#/greetings/s/hi")).should("have.text", "Hola"); - - cy.get(cesc2("#/greetings/s/l1")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/l2")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/l3")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/l4")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/l5")).should("have.text", "Hola"); - - cy.get(cesc2("#/greetings/s/c1")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/c2")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/c3")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/c4")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/c5")).should("have.text", "Hello"); - - cy.get(cesc2("#/greetings/s/nm1")).should("not.exist"); - cy.get(cesc2("#/greetings/s/nm2")).should("not.exist"); - cy.get(cesc2("#/greetings/s/nm3")).should("not.exist"); - cy.get(cesc2("#/greetings/s/nm4")).should("not.exist"); - - cy.get(cesc2("#/greetings/s/pNoMatch")).should( - "have.text", - "Four no matches:", - ); - - cy.get(cesc2("#/greetings/s/s/hi")).should("have.text", "Marhaban"); - - cy.get(cesc2("#/greetings/s/s/l1")).should("have.text", "Marhaban"); - cy.get(cesc2("#/greetings/s/s/l2")).should("have.text", "Marhaban"); - cy.get(cesc2("#/greetings/s/s/l3")).should("have.text", "Marhaban"); - cy.get(cesc2("#/greetings/s/s/l4")).should("have.text", "Marhaban"); - cy.get(cesc2("#/greetings/s/s/l5")).should("have.text", "Marhaban"); - - cy.get(cesc2("#/greetings/s/s/m1")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/s/m2")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/s/m3")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/s/m4")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/s/m5")).should("have.text", "Hola"); - - cy.get(cesc2("#/greetings/s/s/c1")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/s/c2")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/s/c3")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/s/c4")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/s/c5")).should("have.text", "Hello"); - - cy.get(cesc2("#/greetings/s/s/nm1")).should("not.exist"); - cy.get(cesc2("#/greetings/s/s/nm2")).should("not.exist"); - cy.get(cesc2("#/greetings/s/s/nm3")).should("not.exist"); - cy.get(cesc2("#/greetings/s/s/nm4")).should("not.exist"); - - cy.get(cesc2("#/greetings/s/s/pNoMatch")).should( - "have.text", - "Four no matches:", - ); - }); - - it("external content cannot reach outside namespace, external has namespace, with copyFromURI", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -
- -

Don't get this: Bye

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/hi")).should("have.text", "Bye"); - - cy.get(cesc2("#/greetings/hi")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/c1")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/c2")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/c3")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/c4")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/c5")).should("have.text", "Hello"); - - cy.get(cesc2("#/greetings/nm1")).should("not.exist"); - cy.get(cesc2("#/greetings/nm2")).should("not.exist"); - cy.get(cesc2("#/greetings/nm3")).should("not.exist"); - cy.get(cesc2("#/greetings/nm4")).should("not.exist"); - - cy.get(cesc2("#/greetings/pNoMatch")).should( - "have.text", - "Four no matches:", - ); - - cy.get(cesc2("#/greetings/s/hi")).should("have.text", "Hola"); - - cy.get(cesc2("#/greetings/s/l1")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/l2")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/l3")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/l4")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/l5")).should("have.text", "Hola"); - - cy.get(cesc2("#/greetings/s/c1")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/c2")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/c3")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/c4")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/c5")).should("have.text", "Hello"); - - cy.get(cesc2("#/greetings/s/nm1")).should("not.exist"); - cy.get(cesc2("#/greetings/s/nm2")).should("not.exist"); - cy.get(cesc2("#/greetings/s/nm3")).should("not.exist"); - cy.get(cesc2("#/greetings/s/nm4")).should("not.exist"); - - cy.get(cesc2("#/greetings/s/pNoMatch")).should( - "have.text", - "Four no matches:", - ); - - cy.get(cesc2("#/greetings/s/s/hi")).should("have.text", "Marhaban"); - - cy.get(cesc2("#/greetings/s/s/l1")).should("have.text", "Marhaban"); - cy.get(cesc2("#/greetings/s/s/l2")).should("have.text", "Marhaban"); - cy.get(cesc2("#/greetings/s/s/l3")).should("have.text", "Marhaban"); - cy.get(cesc2("#/greetings/s/s/l4")).should("have.text", "Marhaban"); - cy.get(cesc2("#/greetings/s/s/l5")).should("have.text", "Marhaban"); - - cy.get(cesc2("#/greetings/s/s/m1")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/s/m2")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/s/m3")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/s/m4")).should("have.text", "Hola"); - cy.get(cesc2("#/greetings/s/s/m5")).should("have.text", "Hola"); - - cy.get(cesc2("#/greetings/s/s/c1")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/s/c2")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/s/c3")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/s/c4")).should("have.text", "Hello"); - cy.get(cesc2("#/greetings/s/s/c5")).should("have.text", "Hello"); - - cy.get(cesc2("#/greetings/s/s/nm1")).should("not.exist"); - cy.get(cesc2("#/greetings/s/s/nm2")).should("not.exist"); - cy.get(cesc2("#/greetings/s/s/nm3")).should("not.exist"); - cy.get(cesc2("#/greetings/s/s/nm4")).should("not.exist"); - - cy.get(cesc2("#/greetings/s/s/pNoMatch")).should( - "have.text", - "Four no matches:", - ); - }); - - it("external content inside external content cannot reach outside namespace", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

Don't get this 2: Leave

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/hi")).should("have.text", "Leave"); - - cy.get(cesc2("#/greet/hi")).should("have.text", "Bye"); - - cy.get(cesc2("#/greet/greetings/hi")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/c1")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/c2")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/c3")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/c4")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/c5")).should("have.text", "Hello"); - - cy.get(cesc2("#/greet/greetings/s/hi")).should("have.text", "Hola"); - cy.get(cesc2("#/greet/greetings/s/l1")).should("have.text", "Hola"); - cy.get(cesc2("#/greet/greetings/s/c1")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/s/c2")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/s/c3")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/s/c4")).should("have.text", "Hello"); - - cy.get(cesc2("#/greet/greetings/s/s/hi")).should( - "have.text", - "Marhaban", - ); - cy.get(cesc2("#/greet/greetings/s/s/l1")).should( - "have.text", - "Marhaban", - ); - cy.get(cesc2("#/greet/greetings/s/s/m1")).should("have.text", "Hola"); - cy.get(cesc2("#/greet/greetings/s/s/c1")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/s/s/c2")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/s/s/c3")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/s/s/c4")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/s/s/c5")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/s/s/c5")).should("have.text", "Hello"); - }); - - it("external content inside external content cannot reach outside namespace, external is single section", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

Don't get this 2: Leave

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/hi")).should("have.text", "Leave"); - - cy.get(cesc2("#/greet/hi")).should("have.text", "Bye"); - - cy.get(cesc2("#/greet/greetings/hi")).should("have.text", "Hello"); - - cy.get(cesc2("#/greet/greetings/c1")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/c2")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/c3")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/c4")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/c5")).should("have.text", "Hello"); - - cy.get(cesc2("#/greet/greetings/s/hi")).should("have.text", "Hola"); - - cy.get(cesc2("#/greet/greetings/s/l1")).should("have.text", "Hola"); - cy.get(cesc2("#/greet/greetings/s/l2")).should("have.text", "Hola"); - cy.get(cesc2("#/greet/greetings/s/l3")).should("have.text", "Hola"); - cy.get(cesc2("#/greet/greetings/s/l4")).should("have.text", "Hola"); - cy.get(cesc2("#/greet/greetings/s/l5")).should("have.text", "Hola"); - cy.get(cesc2("#/greet/greetings/s/c1")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/s/c2")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/s/c3")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/s/c4")).should("have.text", "Hello"); - - cy.get(cesc2("#/greet/greetings/s/s/hi")).should( - "have.text", - "Marhaban", - ); - cy.get(cesc2("#/greet/greetings/s/s/l1")).should( - "have.text", - "Marhaban", - ); - cy.get(cesc2("#/greet/greetings/s/s/m1")).should("have.text", "Hola"); - cy.get(cesc2("#/greet/greetings/s/s/c1")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/s/s/c2")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/s/s/c3")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/s/s/c4")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/s/s/c5")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/s/s/c5")).should("have.text", "Hello"); - }); - - it("external content inside external content cannot reach outside namespace, with copyFromURI", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -
- -

Don't get this 2: Leave

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/hi")).should("have.text", "Leave"); - - cy.get(cesc2("#/greet/hi")).should("have.text", "Bye"); - - cy.get(cesc2("#/greet/greetings/hi")).should("have.text", "Hello"); - - cy.get(cesc2("#/greet/greetings/c1")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/c2")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/c3")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/c4")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/c5")).should("have.text", "Hello"); - - cy.get(cesc2("#/greet/greetings/s/hi")).should("have.text", "Hola"); - - cy.get(cesc2("#/greet/greetings/s/l1")).should("have.text", "Hola"); - cy.get(cesc2("#/greet/greetings/s/l2")).should("have.text", "Hola"); - cy.get(cesc2("#/greet/greetings/s/l3")).should("have.text", "Hola"); - cy.get(cesc2("#/greet/greetings/s/l4")).should("have.text", "Hola"); - cy.get(cesc2("#/greet/greetings/s/l5")).should("have.text", "Hola"); - cy.get(cesc2("#/greet/greetings/s/c1")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/s/c2")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/s/c3")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/s/c4")).should("have.text", "Hello"); - - cy.get(cesc2("#/greet/greetings/s/s/hi")).should( - "have.text", - "Marhaban", - ); - cy.get(cesc2("#/greet/greetings/s/s/l1")).should( - "have.text", - "Marhaban", - ); - cy.get(cesc2("#/greet/greetings/s/s/m1")).should("have.text", "Hola"); - cy.get(cesc2("#/greet/greetings/s/s/c1")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/s/s/c2")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/s/s/c3")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/s/s/c4")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/s/s/c5")).should("have.text", "Hello"); - cy.get(cesc2("#/greet/greetings/s/s/c5")).should("have.text", "Hello"); - }); - - it("copy of template source maintained when withheld", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Number of points:

- - - - - - - - -

A_1 =

-

A_2 =

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A1="); - }); - cy.get(cesc("#\\/m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A2="); - }); - - cy.log("Add point"); - - cy.get(cesc("#\\/n") + " textarea").type("1{enter}", { force: true }); - cy.get(cesc("#\\/m1")).should("contain.text", "A1=(1,1)"); - cy.get(cesc("#\\/m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A1=(1,1)"); - }); - cy.get(cesc("#\\/m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A2="); - }); - - cy.log("Move point"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/t1/A", - args: { x: -3, y: 7 }, - }); - }); - - cy.get(cesc("#\\/m1")).should("contain.text", "A1=(−3,7)"); - cy.get(cesc("#\\/m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A1=(−3,7)"); - }); - cy.get(cesc("#\\/m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A2="); - }); - - cy.log("Remove point"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}0{enter}", { - force: true, - }); - - cy.get(cesc("#\\/m1")).should("not.contain.text", "A1=(−3,7)"); - cy.get(cesc("#\\/m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A1="); - }); - cy.get(cesc("#\\/m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A2="); - }); - - cy.log( - "Remember coordinates when restore point since copy was maintained", - ); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}1{enter}", { - force: true, - }); - - cy.get(cesc("#\\/m1") + " .mjx-mrow").should( - "contain.text", - "A1=(−3,7)", - ); - cy.get(cesc("#\\/m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A1=(−3,7)"); - }); - cy.get(cesc("#\\/m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A2="); - }); - - cy.log("Add second point"); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - cy.get(cesc("#\\/m2") + " .mjx-mrow").should( - "contain.text", - "A2=(2,1)", - ); - cy.get(cesc("#\\/m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A1=(−3,7)"); - }); - cy.get(cesc("#\\/m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A2=(2,1)"); - }); - - cy.log("Move second point"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - win.callAction1({ - actionName: "movePoint", - componentName: "/t2/A", - args: { x: 5, y: -4 }, - }); - }); - - cy.get(cesc("#\\/m2") + " .mjx-mrow").should( - "contain.text", - "A2=(5,−4)", - ); - cy.get(cesc("#\\/m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A1=(−3,7)"); - }); - cy.get(cesc("#\\/m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A2=(5,−4)"); - }); - - cy.log("Remove both points"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}0{enter}", { - force: true, - }); - - cy.get(cesc("#\\/m1") + " .mjx-mrow").should( - "not.contain.text", - "A1=(−3,7)", - ); - cy.get(cesc("#\\/m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A1="); - }); - cy.get(cesc("#\\/m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A2="); - }); - - cy.log("Remember coordinates of both points"); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - cy.get(cesc("#\\/m1") + " .mjx-mrow").should( - "contain.text", - "A1=(−3,7)", - ); - cy.get(cesc("#\\/m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A1=(−3,7)"); - }); - cy.get(cesc("#\\/m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A2=(5,−4)"); - }); - }); - - it("copy of template source maintained when withheld, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Number of points:

- - - - - - - - -

A_1 = $(t1/A{displayDigits="3"})

-

A_2 = $(t2/A{displayDigits="3"})

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A1="); - }); - cy.get(cesc("#\\/m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A2="); - }); - - cy.log("Add point"); - - cy.get(cesc("#\\/n") + " textarea").type("1{enter}", { force: true }); - cy.get(cesc("#\\/m1")).should("contain.text", "A1=(1,1)"); - cy.get(cesc("#\\/m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A1=(1,1)"); - }); - cy.get(cesc("#\\/m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A2="); - }); - - cy.log("Move point"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/t1/A", - args: { x: -3, y: 7 }, - }); - }); - - cy.get(cesc("#\\/m1")).should("contain.text", "A1=(−3,7)"); - cy.get(cesc("#\\/m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A1=(−3,7)"); - }); - cy.get(cesc("#\\/m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A2="); - }); - - cy.log("Remove point"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}0{enter}", { - force: true, - }); - - cy.get(cesc("#\\/m1")).should("not.contain.text", "A1=(−3,7)"); - cy.get(cesc("#\\/m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A1="); - }); - cy.get(cesc("#\\/m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A2="); - }); - - cy.log( - "Remember coordinates when restore point since copy was maintained", - ); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}1{enter}", { - force: true, - }); - - cy.get(cesc("#\\/m1") + " .mjx-mrow").should( - "contain.text", - "A1=(−3,7)", - ); - cy.get(cesc("#\\/m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A1=(−3,7)"); - }); - cy.get(cesc("#\\/m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A2="); - }); - - cy.log("Add second point"); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - cy.get(cesc("#\\/m2") + " .mjx-mrow").should( - "contain.text", - "A2=(2,1)", - ); - cy.get(cesc("#\\/m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A1=(−3,7)"); - }); - cy.get(cesc("#\\/m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A2=(2,1)"); - }); - - cy.log("Move second point"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - win.callAction1({ - actionName: "movePoint", - componentName: "/t2/A", - args: { x: 5, y: -4 }, - }); - }); - - cy.get(cesc("#\\/m2") + " .mjx-mrow").should( - "contain.text", - "A2=(5,−4)", - ); - cy.get(cesc("#\\/m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A1=(−3,7)"); - }); - cy.get(cesc("#\\/m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A2=(5,−4)"); - }); - - cy.log("Remove both points"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}0{enter}", { - force: true, - }); - - cy.get(cesc("#\\/m1") + " .mjx-mrow").should( - "not.contain.text", - "A1=(−3,7)", - ); - cy.get(cesc("#\\/m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A1="); - }); - cy.get(cesc("#\\/m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A2="); - }); - - cy.log("Remember coordinates of both points"); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - cy.get(cesc("#\\/m1") + " .mjx-mrow").should( - "contain.text", - "A1=(−3,7)", - ); - cy.get(cesc("#\\/m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A1=(−3,7)"); - }); - cy.get(cesc("#\\/m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("A2=(5,−4)"); - }); - }); - - it("trim whitespace off source", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - Hello -

there

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/hi")).should("have.text", "Hello"); - cy.get(cesc("#\\/_p1")).should("have.text", "Hello there"); - }); - - it("trim whitespace off source, with copySource", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - Hello -

there

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/hi")).should("have.text", "Hello"); - cy.get(cesc("#\\/_p1")).should("have.text", "Hello there"); - }); - - it("copy of external content retains desired variant", () => { - let doenetML = ` - a - - `; - - cy.get("#testRunner_toggleControls").click(); - cy.get("#testRunner_allowLocalState").click(); - cy.wait(100); - cy.get("#testRunner_toggleControls").click(); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: 1, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let catInd, choiceOrder; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/problem1/_select1"].stateValues - .currentVariantName, - ).eq("cat"); - let choices = - stateVariables["/problem1/_choiceinput1"].stateValues - .choiceTexts; - catInd = choices.indexOf("meow") + 1; - choiceOrder = - stateVariables["/problem1/_choiceinput1"].stateValues - .choiceOrder; - - cy.get( - cesc2(`#/problem1/_choiceinput1_choice${catInd}_input`), - ).click(); - }); - - cy.get(cesc2(`#/problem1/_choiceinput1_submit`)).click(); - cy.get(cesc2(`#/problem1/_choiceinput1_correct`)).should("be.visible"); - - cy.wait(2000); // make sure 1 second debounce occurred - - cy.reload(); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: 1, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - // wait until core is loaded - cy.waitUntil(() => - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let foundIt = Boolean( - stateVariables["/problem1/_choiceinput1"]?.stateValues - ?.choiceTexts, - ); - return foundIt; - }), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/problem1/_select1"].stateValues - .currentVariantName, - ).eq("cat"); - expect( - stateVariables["/problem1/_choiceinput1"].stateValues - .choiceOrder, - ).eqls(choiceOrder); - let choices = [ - ...stateVariables["/problem1/_choiceinput1"].stateValues - .choiceTexts, - ]; - expect(choices.indexOf("meow") + 1).eq(catInd); - }); - }); - - it("copy of external content retains desired variant, with copyfromuri", () => { - let doenetML = ` - a - - `; - - cy.get("#testRunner_toggleControls").click(); - cy.get("#testRunner_allowLocalState").click(); - cy.wait(100); - cy.get("#testRunner_toggleControls").click(); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: 1, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let catInd, choiceOrder; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/problem1/_select1"].stateValues - .currentVariantName, - ).eq("cat"); - let choices = - stateVariables["/problem1/_choiceinput1"].stateValues - .choiceTexts; - catInd = choices.indexOf("meow") + 1; - choiceOrder = - stateVariables["/problem1/_choiceinput1"].stateValues - .choiceOrder; - - cy.get( - cesc2(`#/problem1/_choiceinput1_choice${catInd}_input`), - ).click(); - }); - - cy.get(cesc2(`#/problem1/_choiceinput1_submit`)).click(); - cy.get(cesc2(`#/problem1/_choiceinput1_correct`)).should("be.visible"); - - cy.wait(2000); // make sure 1 second debounce occurred - - cy.reload(); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: 1, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - // wait until core is loaded - cy.waitUntil(() => - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let foundIt = Boolean( - stateVariables["/problem1/_choiceinput1"]?.stateValues - ?.choiceTexts, - ); - return foundIt; - }), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/problem1/_select1"].stateValues - .currentVariantName, - ).eq("cat"); - expect( - stateVariables["/problem1/_choiceinput1"].stateValues - .choiceOrder, - ).eqls(choiceOrder); - let choices = [ - ...stateVariables["/problem1/_choiceinput1"].stateValues - .choiceTexts, - ]; - expect(choices.indexOf("meow") + 1).eq(catInd); - }); - }); - - it("copy of external content retains desired variant, no problem in external content", () => { - let doenetML = ` - a - - `; - - cy.get("#testRunner_toggleControls").click(); - cy.get("#testRunner_allowLocalState").click(); - cy.wait(100); - cy.get("#testRunner_toggleControls").click(); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: 1, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let catInd, choiceOrder; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/problem1/_select1"].stateValues - .currentVariantName, - ).eq("cat"); - let choices = - stateVariables["/problem1/_choiceinput1"].stateValues - .choiceTexts; - catInd = choices.indexOf("meow") + 1; - choiceOrder = - stateVariables["/problem1/_choiceinput1"].stateValues - .choiceOrder; - - cy.get( - cesc2(`#/problem1/_choiceinput1_choice${catInd}_input`), - ).click(); - }); - - cy.get(cesc2(`#/problem1/_choiceinput1_submit`)).click(); - cy.get(cesc2(`#/problem1/_choiceinput1_correct`)).should("be.visible"); - - cy.wait(2000); // make sure 1 second debounce occurred - - cy.reload(); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: 1, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - // wait until core is loaded - cy.waitUntil(() => - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let foundIt = Boolean( - stateVariables["/problem1/_choiceinput1"]?.stateValues - ?.choiceTexts, - ); - return foundIt; - }), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/problem1/_select1"].stateValues - .currentVariantName, - ).eq("cat"); - expect( - stateVariables["/problem1/_choiceinput1"].stateValues - .choiceOrder, - ).eqls(choiceOrder); - let choices = [ - ...stateVariables["/problem1/_choiceinput1"].stateValues - .choiceTexts, - ]; - expect(choices.indexOf("meow") + 1).eq(catInd); - }); - }); - - it("copy with newNamespace and name retains original names, even with group", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

values: 1 2 3

- -
- - $p1 - - - - - - $_section1 - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - cy.get(cesc2("#/_number1")).should("have.text", "1"); - cy.get(cesc2("#/_number2")).should("have.text", "2"); - cy.get(cesc2("#/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/p1/_number1")).should("have.text", "1"); - cy.get(cesc2("#/p1/_number2")).should("have.text", "2"); - cy.get(cesc2("#/p1/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/p1a/_number1")).should("have.text", "1"); - cy.get(cesc2("#/p1a/_number2")).should("have.text", "2"); - cy.get(cesc2("#/p1a/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/p1b/_number1")).should("have.text", "1"); - cy.get(cesc2("#/p1b/_number2")).should("have.text", "2"); - cy.get(cesc2("#/p1b/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/s1b/p1/_number1")).should("have.text", "1"); - cy.get(cesc2("#/s1b/p1/_number2")).should("have.text", "2"); - cy.get(cesc2("#/s1b/p1/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/_p1")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/p1a")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/p1b")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/s1b/p1")).should("have.text", "values: 1 2 3"); - - cy.get(cesc2("#/_section1")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 1\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#/s1a")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 3\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#/s1b")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 5\s*values: 1 2 3/)).not.be.null; - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let c2p = - stateVariables["/_document1"].activeChildren[6].componentName; - let c4p = - stateVariables["/_document1"].activeChildren[10].componentName; - let c6p = - stateVariables["/_document1"].activeChildren[14].componentName; - let c7s = - stateVariables["/_document1"].activeChildren[16].componentName; - let c9s = - stateVariables["/_document1"].activeChildren[20].componentName; - - cy.get(cesc2("#" + c2p)).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#" + c4p)).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#" + c6p)).should("have.text", "values: 1 2 3"); - - cy.get(cesc2("#" + c7s)) - .invoke("text") - .then((text) => { - expect(text.match(/Section 2\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#" + c9s)) - .invoke("text") - .then((text) => { - expect(text.match(/Section 4\s*values: 1 2 3/)).not.be.null; - }); - - // put in window just so happens after above - cy.window().then(async (win) => { - expect(stateVariables["/p1/_number1"].stateValues.value).eq(1); - expect(stateVariables["/p1/_number2"].stateValues.value).eq(2); - expect(stateVariables["/p1/_number3"].stateValues.value).eq(3); - - // c2p's children should have gotten unique names (so begin with two underscores) - let c2pChildNames = stateVariables[c2p].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - expect(c2pChildNames[0].slice(0, 3)).eq("/__"); - expect(c2pChildNames[1].slice(0, 3)).eq("/__"); - expect(c2pChildNames[2].slice(0, 3)).eq("/__"); - expect(stateVariables[c2pChildNames[0]].stateValues.value).eq( - 1, - ); - expect(stateVariables[c2pChildNames[1]].stateValues.value).eq( - 2, - ); - expect(stateVariables[c2pChildNames[2]].stateValues.value).eq( - 3, - ); - - // c4p's children should have gotten unique names (so begin with two underscores) - let c4pChildNames = stateVariables[c4p].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - expect(c4pChildNames[0].slice(0, 3)).eq("/__"); - expect(c4pChildNames[1].slice(0, 3)).eq("/__"); - expect(c4pChildNames[2].slice(0, 3)).eq("/__"); - expect(stateVariables[c4pChildNames[0]].stateValues.value).eq( - 1, - ); - expect(stateVariables[c4pChildNames[1]].stateValues.value).eq( - 2, - ); - expect(stateVariables[c4pChildNames[2]].stateValues.value).eq( - 3, - ); - - // c6p's children should have gotten unique names (so begin with two underscores) - let c6pChildNames = stateVariables[c6p].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - expect(c6pChildNames[0].slice(0, 3)).eq("/__"); - expect(c6pChildNames[1].slice(0, 3)).eq("/__"); - expect(c6pChildNames[2].slice(0, 3)).eq("/__"); - expect(stateVariables[c6pChildNames[0]].stateValues.value).eq( - 1, - ); - expect(stateVariables[c6pChildNames[1]].stateValues.value).eq( - 2, - ); - expect(stateVariables[c6pChildNames[2]].stateValues.value).eq( - 3, - ); - - // c7s's grandchildren should have gotten unique names (so begin with two underscores) - let c7sChildName = stateVariables[c7s].activeChildren.filter( - (x) => x.componentName, - )[0].componentName; - let c7sGrandChildNames = stateVariables[ - c7sChildName - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(c7sGrandChildNames[0].slice(0, 3)).eq("/__"); - expect(c7sGrandChildNames[1].slice(0, 3)).eq("/__"); - expect(c7sGrandChildNames[2].slice(0, 3)).eq("/__"); - expect( - stateVariables[c7sGrandChildNames[0]].stateValues.value, - ).eq(1); - expect( - stateVariables[c7sGrandChildNames[1]].stateValues.value, - ).eq(2); - expect( - stateVariables[c7sGrandChildNames[2]].stateValues.value, - ).eq(3); - - // s1a's grandchildren should have gotten unique names (so begin with two underscores) - let s1aChildName = stateVariables["/s1a"].activeChildren.filter( - (x) => x.componentName, - )[0].componentName; - let s1aGrandChildNames = stateVariables[ - s1aChildName - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(s1aGrandChildNames[0].slice(0, 3)).eq("/__"); - expect(s1aGrandChildNames[1].slice(0, 3)).eq("/__"); - expect(s1aGrandChildNames[2].slice(0, 3)).eq("/__"); - expect( - stateVariables[s1aGrandChildNames[0]].stateValues.value, - ).eq(1); - expect( - stateVariables[s1aGrandChildNames[1]].stateValues.value, - ).eq(2); - expect( - stateVariables[s1aGrandChildNames[2]].stateValues.value, - ).eq(3); - - // c9s's grandchildren should have gotten unique names (so begin with two underscores) - let c9sChildName = stateVariables[c9s].activeChildren.filter( - (x) => x.componentName, - )[0].componentName; - let c9sGrandChildNames = stateVariables[ - c9sChildName - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(c9sGrandChildNames[0].slice(0, 3)).eq("/__"); - expect(c9sGrandChildNames[1].slice(0, 3)).eq("/__"); - expect(c9sGrandChildNames[2].slice(0, 3)).eq("/__"); - expect( - stateVariables[c9sGrandChildNames[0]].stateValues.value, - ).eq(1); - expect( - stateVariables[c9sGrandChildNames[1]].stateValues.value, - ).eq(2); - expect( - stateVariables[c9sGrandChildNames[2]].stateValues.value, - ).eq(3); - - // s1b's grandchildren should have retained their original names - let s1bChildName = stateVariables["/s1b"].activeChildren.filter( - (x) => x.componentName, - )[0].componentName; - let s1bGrandChildNames = stateVariables[ - s1bChildName - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(s1bGrandChildNames[0]).eq("/s1b/p1/_number1"); - expect(s1bGrandChildNames[1]).eq("/s1b/p1/_number2"); - expect(s1bGrandChildNames[2]).eq("/s1b/p1/_number3"); - expect( - stateVariables[s1bGrandChildNames[0]].stateValues.value, - ).eq(1); - expect( - stateVariables[s1bGrandChildNames[1]].stateValues.value, - ).eq(2); - expect( - stateVariables[s1bGrandChildNames[2]].stateValues.value, - ).eq(3); - }); - }); - }); - - it("copy with newNamespace and name retains original names, even with group, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

values: 1 2 3

- -
$_p1{newNamespace name="p1"}
- - $p1 - $p1{name="p1a"} - $p1{newNamespace} - $p1{newNamespace name="p1b"} - $p1a{newNamespace} - - $_section1 - $_section1{name="s1a"} - $_section1{newNamespace} - $_section1{newNamespace name="s1b"} - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - cy.get(cesc2("#/_number1")).should("have.text", "1"); - cy.get(cesc2("#/_number2")).should("have.text", "2"); - cy.get(cesc2("#/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/p1/_number1")).should("have.text", "1"); - cy.get(cesc2("#/p1/_number2")).should("have.text", "2"); - cy.get(cesc2("#/p1/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/p1a/_number1")).should("have.text", "1"); - cy.get(cesc2("#/p1a/_number2")).should("have.text", "2"); - cy.get(cesc2("#/p1a/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/p1b/_number1")).should("have.text", "1"); - cy.get(cesc2("#/p1b/_number2")).should("have.text", "2"); - cy.get(cesc2("#/p1b/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/s1b/p1/_number1")).should("have.text", "1"); - cy.get(cesc2("#/s1b/p1/_number2")).should("have.text", "2"); - cy.get(cesc2("#/s1b/p1/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/_p1")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/p1a")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/p1b")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/s1b/p1")).should("have.text", "values: 1 2 3"); - - cy.get(cesc2("#/_section1")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 1\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#/s1a")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 3\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#/s1b")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 5\s*values: 1 2 3/)).not.be.null; - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let c2p = - stateVariables["/_document1"].activeChildren[6].componentName; - let c4p = - stateVariables["/_document1"].activeChildren[10].componentName; - let c6p = - stateVariables["/_document1"].activeChildren[14].componentName; - let c7s = - stateVariables["/_document1"].activeChildren[16].componentName; - let c9s = - stateVariables["/_document1"].activeChildren[20].componentName; - - cy.get(cesc2("#" + c2p)).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#" + c4p)).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#" + c6p)).should("have.text", "values: 1 2 3"); - - cy.get(cesc2("#" + c7s)) - .invoke("text") - .then((text) => { - expect(text.match(/Section 2\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#" + c9s)) - .invoke("text") - .then((text) => { - expect(text.match(/Section 4\s*values: 1 2 3/)).not.be.null; - }); - - // put in window just so happens after above - cy.window().then(async (win) => { - expect(stateVariables["/p1/_number1"].stateValues.value).eq(1); - expect(stateVariables["/p1/_number2"].stateValues.value).eq(2); - expect(stateVariables["/p1/_number3"].stateValues.value).eq(3); - - // c2p's children should have gotten unique names (so begin with two underscores) - let c2pChildNames = stateVariables[c2p].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - expect(c2pChildNames[0].slice(0, 3)).eq("/__"); - expect(c2pChildNames[1].slice(0, 3)).eq("/__"); - expect(c2pChildNames[2].slice(0, 3)).eq("/__"); - expect(stateVariables[c2pChildNames[0]].stateValues.value).eq( - 1, - ); - expect(stateVariables[c2pChildNames[1]].stateValues.value).eq( - 2, - ); - expect(stateVariables[c2pChildNames[2]].stateValues.value).eq( - 3, - ); - - // c4p's children should have gotten unique names (so begin with two underscores) - let c4pChildNames = stateVariables[c4p].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - expect(c4pChildNames[0].slice(0, 3)).eq("/__"); - expect(c4pChildNames[1].slice(0, 3)).eq("/__"); - expect(c4pChildNames[2].slice(0, 3)).eq("/__"); - expect(stateVariables[c4pChildNames[0]].stateValues.value).eq( - 1, - ); - expect(stateVariables[c4pChildNames[1]].stateValues.value).eq( - 2, - ); - expect(stateVariables[c4pChildNames[2]].stateValues.value).eq( - 3, - ); - - // c6p's children should have gotten unique names (so begin with two underscores) - let c6pChildNames = stateVariables[c6p].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - expect(c6pChildNames[0].slice(0, 3)).eq("/__"); - expect(c6pChildNames[1].slice(0, 3)).eq("/__"); - expect(c6pChildNames[2].slice(0, 3)).eq("/__"); - expect(stateVariables[c6pChildNames[0]].stateValues.value).eq( - 1, - ); - expect(stateVariables[c6pChildNames[1]].stateValues.value).eq( - 2, - ); - expect(stateVariables[c6pChildNames[2]].stateValues.value).eq( - 3, - ); - - // c7s's grandchildren should have gotten unique names (so begin with two underscores) - let c7sChildName = stateVariables[c7s].activeChildren.filter( - (x) => x.componentName, - )[0].componentName; - let c7sGrandChildNames = stateVariables[ - c7sChildName - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(c7sGrandChildNames[0].slice(0, 3)).eq("/__"); - expect(c7sGrandChildNames[1].slice(0, 3)).eq("/__"); - expect(c7sGrandChildNames[2].slice(0, 3)).eq("/__"); - expect( - stateVariables[c7sGrandChildNames[0]].stateValues.value, - ).eq(1); - expect( - stateVariables[c7sGrandChildNames[1]].stateValues.value, - ).eq(2); - expect( - stateVariables[c7sGrandChildNames[2]].stateValues.value, - ).eq(3); - - // s1a's grandchildren should have gotten unique names (so begin with two underscores) - let s1aChildName = stateVariables["/s1a"].activeChildren.filter( - (x) => x.componentName, - )[0].componentName; - let s1aGrandChildNames = stateVariables[ - s1aChildName - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(s1aGrandChildNames[0].slice(0, 3)).eq("/__"); - expect(s1aGrandChildNames[1].slice(0, 3)).eq("/__"); - expect(s1aGrandChildNames[2].slice(0, 3)).eq("/__"); - expect( - stateVariables[s1aGrandChildNames[0]].stateValues.value, - ).eq(1); - expect( - stateVariables[s1aGrandChildNames[1]].stateValues.value, - ).eq(2); - expect( - stateVariables[s1aGrandChildNames[2]].stateValues.value, - ).eq(3); - - // c9s's grandchildren should have gotten unique names (so begin with two underscores) - let c9sChildName = stateVariables[c9s].activeChildren.filter( - (x) => x.componentName, - )[0].componentName; - let c9sGrandChildNames = stateVariables[ - c9sChildName - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(c9sGrandChildNames[0].slice(0, 3)).eq("/__"); - expect(c9sGrandChildNames[1].slice(0, 3)).eq("/__"); - expect(c9sGrandChildNames[2].slice(0, 3)).eq("/__"); - expect( - stateVariables[c9sGrandChildNames[0]].stateValues.value, - ).eq(1); - expect( - stateVariables[c9sGrandChildNames[1]].stateValues.value, - ).eq(2); - expect( - stateVariables[c9sGrandChildNames[2]].stateValues.value, - ).eq(3); - - // s1b's grandchildren should have retained their original names - let s1bChildName = stateVariables["/s1b"].activeChildren.filter( - (x) => x.componentName, - )[0].componentName; - let s1bGrandChildNames = stateVariables[ - s1bChildName - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(s1bGrandChildNames[0]).eq("/s1b/p1/_number1"); - expect(s1bGrandChildNames[1]).eq("/s1b/p1/_number2"); - expect(s1bGrandChildNames[2]).eq("/s1b/p1/_number3"); - expect( - stateVariables[s1bGrandChildNames[0]].stateValues.value, - ).eq(1); - expect( - stateVariables[s1bGrandChildNames[1]].stateValues.value, - ).eq(2); - expect( - stateVariables[s1bGrandChildNames[2]].stateValues.value, - ).eq(3); - }); - }); - }); - - it("copy with newNamespace retains original names, even with group, with copySource", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

values: 1 2 3

- -

- -

-

- -

-
- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - cy.get(cesc2("#/_number1")).should("have.text", "1"); - cy.get(cesc2("#/_number2")).should("have.text", "2"); - cy.get(cesc2("#/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/p1a/_number1")).should("have.text", "1"); - cy.get(cesc2("#/p1a/_number2")).should("have.text", "2"); - cy.get(cesc2("#/p1a/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/p1b/_number1")).should("have.text", "1"); - cy.get(cesc2("#/p1b/_number2")).should("have.text", "2"); - cy.get(cesc2("#/p1b/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/p1c/_number1")).should("have.text", "1"); - cy.get(cesc2("#/p1c/_number2")).should("have.text", "2"); - cy.get(cesc2("#/p1c/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/s1b/p1a/_number1")).should("have.text", "1"); - cy.get(cesc2("#/s1b/p1a/_number2")).should("have.text", "2"); - cy.get(cesc2("#/s1b/p1a/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/_p1")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/p1a")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/p1b")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/p1c")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/s1b/p1a")).should("have.text", "values: 1 2 3"); - - cy.get(cesc2("#/_section1")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 1\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#/s1a")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 2\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#/s1b")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 3\s*values: 1 2 3/)).not.be.null; - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/p1a/_number1"].stateValues.value).eq(1); - expect(stateVariables["/p1a/_number2"].stateValues.value).eq(2); - expect(stateVariables["/p1a/_number3"].stateValues.value).eq(3); - - expect(stateVariables["/p1b/_number1"].stateValues.value).eq(1); - expect(stateVariables["/p1b/_number2"].stateValues.value).eq(2); - expect(stateVariables["/p1b/_number3"].stateValues.value).eq(3); - - expect(stateVariables["/p1c/_number1"].stateValues.value).eq(1); - expect(stateVariables["/p1c/_number2"].stateValues.value).eq(2); - expect(stateVariables["/p1c/_number3"].stateValues.value).eq(3); - - // s1a's grandchildren should have gotten unique names (so begin with two underscores) - let s1aChildName = - stateVariables["/s1a"].activeChildren[0].componentName; - let s1aGrandChildNames = stateVariables[s1aChildName].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - expect(s1aGrandChildNames[0].slice(0, 3)).eq("/__"); - expect(s1aGrandChildNames[1].slice(0, 3)).eq("/__"); - expect(s1aGrandChildNames[2].slice(0, 3)).eq("/__"); - expect(stateVariables[s1aGrandChildNames[0]].stateValues.value).eq( - 1, - ); - expect(stateVariables[s1aGrandChildNames[1]].stateValues.value).eq( - 2, - ); - expect(stateVariables[s1aGrandChildNames[2]].stateValues.value).eq( - 3, - ); - }); - }); - - it("copy with newNamespace and name retains original names, even with group that assigns names", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

values: 1 2 3

- -
- - $p1 - - - - - - $_section1 - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - cy.get(cesc2("#/n1")).should("have.text", "1"); - cy.get(cesc2("#/n2")).should("have.text", "2"); - cy.get(cesc2("#/n3")).should("have.text", "3"); - - cy.get(cesc2("#/p1/n1")).should("have.text", "1"); - cy.get(cesc2("#/p1/n2")).should("have.text", "2"); - cy.get(cesc2("#/p1/n3")).should("have.text", "3"); - - cy.get(cesc2("#/p1a/n1")).should("have.text", "1"); - cy.get(cesc2("#/p1a/n2")).should("have.text", "2"); - cy.get(cesc2("#/p1a/n3")).should("have.text", "3"); - - cy.get(cesc2("#/p1b/n1")).should("have.text", "1"); - cy.get(cesc2("#/p1b/n2")).should("have.text", "2"); - cy.get(cesc2("#/p1b/n3")).should("have.text", "3"); - - cy.get(cesc2("#/s1b/p1/n1")).should("have.text", "1"); - cy.get(cesc2("#/s1b/p1/n2")).should("have.text", "2"); - cy.get(cesc2("#/s1b/p1/n3")).should("have.text", "3"); - - cy.get(cesc2("#/_p1")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/p1a")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/p1b")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/s1b/p1")).should("have.text", "values: 1 2 3"); - - cy.get(cesc2("#/_section1")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 1\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#/s1a")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 3\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#/s1b")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 5\s*values: 1 2 3/)).not.be.null; - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let c2p = - stateVariables["/_document1"].activeChildren[6].componentName; - let c4p = - stateVariables["/_document1"].activeChildren[10].componentName; - let c6p = - stateVariables["/_document1"].activeChildren[14].componentName; - let c7s = - stateVariables["/_document1"].activeChildren[16].componentName; - let c9s = - stateVariables["/_document1"].activeChildren[20].componentName; - - cy.get(cesc2("#" + c2p)).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#" + c4p)).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#" + c6p)).should("have.text", "values: 1 2 3"); - - cy.get(cesc2("#" + c7s)) - .invoke("text") - .then((text) => { - expect(text.match(/Section 2\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#" + c9s)) - .invoke("text") - .then((text) => { - expect(text.match(/Section 4\s*values: 1 2 3/)).not.be.null; - }); - - // put in window just so happens after above - cy.window().then(async (win) => { - expect(stateVariables["/p1/n1"].stateValues.value).eq(1); - expect(stateVariables["/p1/n2"].stateValues.value).eq(2); - expect(stateVariables["/p1/n3"].stateValues.value).eq(3); - - // c2p's children should have gotten unique names (so begin with two underscores) - let c2pChildNames = stateVariables[c2p].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - expect(c2pChildNames[0].slice(0, 3)).eq("/__"); - expect(c2pChildNames[1].slice(0, 3)).eq("/__"); - expect(c2pChildNames[2].slice(0, 3)).eq("/__"); - expect(stateVariables[c2pChildNames[0]].stateValues.value).eq( - 1, - ); - expect(stateVariables[c2pChildNames[1]].stateValues.value).eq( - 2, - ); - expect(stateVariables[c2pChildNames[2]].stateValues.value).eq( - 3, - ); - - // c4p's children should have gotten unique names (so begin with two underscores) - let c4pChildNames = stateVariables[c4p].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - expect(c4pChildNames[0].slice(0, 3)).eq("/__"); - expect(c4pChildNames[1].slice(0, 3)).eq("/__"); - expect(c4pChildNames[2].slice(0, 3)).eq("/__"); - expect(stateVariables[c4pChildNames[0]].stateValues.value).eq( - 1, - ); - expect(stateVariables[c4pChildNames[1]].stateValues.value).eq( - 2, - ); - expect(stateVariables[c4pChildNames[2]].stateValues.value).eq( - 3, - ); - - // c6p's children should have gotten unique names (so begin with two underscores) - let c6pChildNames = stateVariables[c6p].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - expect(c6pChildNames[0].slice(0, 3)).eq("/__"); - expect(c6pChildNames[1].slice(0, 3)).eq("/__"); - expect(c6pChildNames[2].slice(0, 3)).eq("/__"); - expect(stateVariables[c6pChildNames[0]].stateValues.value).eq( - 1, - ); - expect(stateVariables[c6pChildNames[1]].stateValues.value).eq( - 2, - ); - expect(stateVariables[c6pChildNames[2]].stateValues.value).eq( - 3, - ); - - // c7s's grandchildren should have gotten unique names (so begin with two underscores) - let c7sChildName = stateVariables[c7s].activeChildren.filter( - (x) => x.componentName, - )[0].componentName; - let c7sGrandChildNames = stateVariables[ - c7sChildName - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(c7sGrandChildNames[0].slice(0, 3)).eq("/__"); - expect(c7sGrandChildNames[1].slice(0, 3)).eq("/__"); - expect(c7sGrandChildNames[2].slice(0, 3)).eq("/__"); - expect( - stateVariables[c7sGrandChildNames[0]].stateValues.value, - ).eq(1); - expect( - stateVariables[c7sGrandChildNames[1]].stateValues.value, - ).eq(2); - expect( - stateVariables[c7sGrandChildNames[2]].stateValues.value, - ).eq(3); - - // s1a's grandchildren should have gotten unique names (so begin with two underscores) - let s1aChildName = stateVariables["/s1a"].activeChildren.filter( - (x) => x.componentName, - )[0].componentName; - let s1aGrandChildNames = stateVariables[ - s1aChildName - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(s1aGrandChildNames[0].slice(0, 3)).eq("/__"); - expect(s1aGrandChildNames[1].slice(0, 3)).eq("/__"); - expect(s1aGrandChildNames[2].slice(0, 3)).eq("/__"); - expect( - stateVariables[s1aGrandChildNames[0]].stateValues.value, - ).eq(1); - expect( - stateVariables[s1aGrandChildNames[1]].stateValues.value, - ).eq(2); - expect( - stateVariables[s1aGrandChildNames[2]].stateValues.value, - ).eq(3); - - // c9s's grandchildren should have gotten unique names (so begin with two underscores) - let c9sChildName = stateVariables[c9s].activeChildren.filter( - (x) => x.componentName, - )[0].componentName; - let c9sGrandChildNames = stateVariables[ - c9sChildName - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(c9sGrandChildNames[0].slice(0, 3)).eq("/__"); - expect(c9sGrandChildNames[1].slice(0, 3)).eq("/__"); - expect(c9sGrandChildNames[2].slice(0, 3)).eq("/__"); - expect( - stateVariables[c9sGrandChildNames[0]].stateValues.value, - ).eq(1); - expect( - stateVariables[c9sGrandChildNames[1]].stateValues.value, - ).eq(2); - expect( - stateVariables[c9sGrandChildNames[2]].stateValues.value, - ).eq(3); - - // s1b's grandchildren should have retained their original names - let s1bChildName = stateVariables["/s1b"].activeChildren.filter( - (x) => x.componentName, - )[0].componentName; - let s1bGrandChildNames = stateVariables[ - s1bChildName - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(s1bGrandChildNames[0]).eq("/s1b/p1/n1"); - expect(s1bGrandChildNames[1]).eq("/s1b/p1/n2"); - expect(s1bGrandChildNames[2]).eq("/s1b/p1/n3"); - expect( - stateVariables[s1bGrandChildNames[0]].stateValues.value, - ).eq(1); - expect( - stateVariables[s1bGrandChildNames[1]].stateValues.value, - ).eq(2); - expect( - stateVariables[s1bGrandChildNames[2]].stateValues.value, - ).eq(3); - }); - }); - }); - - it("copy with newNamespace and name retains original names, even with group that assigns names, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

values: 1 2 3

- -
$_p1{newNamespace name="p1"}
- - $p1 - $p1{name="p1a"} - $p1{newNamespace} - $p1{newNamespace name="p1b"} - $p1a{newNamespace} - - $_section1 - $_section1{name="s1a"} - $_section1{newNamespace} - $_section1{newNamespace name="s1b"} - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - cy.get(cesc2("#/n1")).should("have.text", "1"); - cy.get(cesc2("#/n2")).should("have.text", "2"); - cy.get(cesc2("#/n3")).should("have.text", "3"); - - cy.get(cesc2("#/p1/n1")).should("have.text", "1"); - cy.get(cesc2("#/p1/n2")).should("have.text", "2"); - cy.get(cesc2("#/p1/n3")).should("have.text", "3"); - - cy.get(cesc2("#/p1a/n1")).should("have.text", "1"); - cy.get(cesc2("#/p1a/n2")).should("have.text", "2"); - cy.get(cesc2("#/p1a/n3")).should("have.text", "3"); - - cy.get(cesc2("#/p1b/n1")).should("have.text", "1"); - cy.get(cesc2("#/p1b/n2")).should("have.text", "2"); - cy.get(cesc2("#/p1b/n3")).should("have.text", "3"); - - cy.get(cesc2("#/s1b/p1/n1")).should("have.text", "1"); - cy.get(cesc2("#/s1b/p1/n2")).should("have.text", "2"); - cy.get(cesc2("#/s1b/p1/n3")).should("have.text", "3"); - - cy.get(cesc2("#/_p1")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/p1a")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/p1b")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/s1b/p1")).should("have.text", "values: 1 2 3"); - - cy.get(cesc2("#/_section1")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 1\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#/s1a")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 3\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#/s1b")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 5\s*values: 1 2 3/)).not.be.null; - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let c2p = - stateVariables["/_document1"].activeChildren[6].componentName; - let c4p = - stateVariables["/_document1"].activeChildren[10].componentName; - let c6p = - stateVariables["/_document1"].activeChildren[14].componentName; - let c7s = - stateVariables["/_document1"].activeChildren[16].componentName; - let c9s = - stateVariables["/_document1"].activeChildren[20].componentName; - - cy.get(cesc2("#" + c2p)).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#" + c4p)).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#" + c6p)).should("have.text", "values: 1 2 3"); - - cy.get(cesc2("#" + c7s)) - .invoke("text") - .then((text) => { - expect(text.match(/Section 2\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#" + c9s)) - .invoke("text") - .then((text) => { - expect(text.match(/Section 4\s*values: 1 2 3/)).not.be.null; - }); - - // put in window just so happens after above - cy.window().then(async (win) => { - expect(stateVariables["/p1/n1"].stateValues.value).eq(1); - expect(stateVariables["/p1/n2"].stateValues.value).eq(2); - expect(stateVariables["/p1/n3"].stateValues.value).eq(3); - - // c2p's children should have gotten unique names (so begin with two underscores) - let c2pChildNames = stateVariables[c2p].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - expect(c2pChildNames[0].slice(0, 3)).eq("/__"); - expect(c2pChildNames[1].slice(0, 3)).eq("/__"); - expect(c2pChildNames[2].slice(0, 3)).eq("/__"); - expect(stateVariables[c2pChildNames[0]].stateValues.value).eq( - 1, - ); - expect(stateVariables[c2pChildNames[1]].stateValues.value).eq( - 2, - ); - expect(stateVariables[c2pChildNames[2]].stateValues.value).eq( - 3, - ); - - // c4p's children should have gotten unique names (so begin with two underscores) - let c4pChildNames = stateVariables[c4p].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - expect(c4pChildNames[0].slice(0, 3)).eq("/__"); - expect(c4pChildNames[1].slice(0, 3)).eq("/__"); - expect(c4pChildNames[2].slice(0, 3)).eq("/__"); - expect(stateVariables[c4pChildNames[0]].stateValues.value).eq( - 1, - ); - expect(stateVariables[c4pChildNames[1]].stateValues.value).eq( - 2, - ); - expect(stateVariables[c4pChildNames[2]].stateValues.value).eq( - 3, - ); - - // c6p's children should have gotten unique names (so begin with two underscores) - let c6pChildNames = stateVariables[c6p].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - expect(c6pChildNames[0].slice(0, 3)).eq("/__"); - expect(c6pChildNames[1].slice(0, 3)).eq("/__"); - expect(c6pChildNames[2].slice(0, 3)).eq("/__"); - expect(stateVariables[c6pChildNames[0]].stateValues.value).eq( - 1, - ); - expect(stateVariables[c6pChildNames[1]].stateValues.value).eq( - 2, - ); - expect(stateVariables[c6pChildNames[2]].stateValues.value).eq( - 3, - ); - - // c7s's grandchildren should have gotten unique names (so begin with two underscores) - let c7sChildName = stateVariables[c7s].activeChildren.filter( - (x) => x.componentName, - )[0].componentName; - let c7sGrandChildNames = stateVariables[ - c7sChildName - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(c7sGrandChildNames[0].slice(0, 3)).eq("/__"); - expect(c7sGrandChildNames[1].slice(0, 3)).eq("/__"); - expect(c7sGrandChildNames[2].slice(0, 3)).eq("/__"); - expect( - stateVariables[c7sGrandChildNames[0]].stateValues.value, - ).eq(1); - expect( - stateVariables[c7sGrandChildNames[1]].stateValues.value, - ).eq(2); - expect( - stateVariables[c7sGrandChildNames[2]].stateValues.value, - ).eq(3); - - // s1a's grandchildren should have gotten unique names (so begin with two underscores) - let s1aChildName = stateVariables["/s1a"].activeChildren.filter( - (x) => x.componentName, - )[0].componentName; - let s1aGrandChildNames = stateVariables[ - s1aChildName - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(s1aGrandChildNames[0].slice(0, 3)).eq("/__"); - expect(s1aGrandChildNames[1].slice(0, 3)).eq("/__"); - expect(s1aGrandChildNames[2].slice(0, 3)).eq("/__"); - expect( - stateVariables[s1aGrandChildNames[0]].stateValues.value, - ).eq(1); - expect( - stateVariables[s1aGrandChildNames[1]].stateValues.value, - ).eq(2); - expect( - stateVariables[s1aGrandChildNames[2]].stateValues.value, - ).eq(3); - - // c9s's grandchildren should have gotten unique names (so begin with two underscores) - let c9sChildName = stateVariables[c9s].activeChildren.filter( - (x) => x.componentName, - )[0].componentName; - let c9sGrandChildNames = stateVariables[ - c9sChildName - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(c9sGrandChildNames[0].slice(0, 3)).eq("/__"); - expect(c9sGrandChildNames[1].slice(0, 3)).eq("/__"); - expect(c9sGrandChildNames[2].slice(0, 3)).eq("/__"); - expect( - stateVariables[c9sGrandChildNames[0]].stateValues.value, - ).eq(1); - expect( - stateVariables[c9sGrandChildNames[1]].stateValues.value, - ).eq(2); - expect( - stateVariables[c9sGrandChildNames[2]].stateValues.value, - ).eq(3); - - // s1b's grandchildren should have retained their original names - let s1bChildName = stateVariables["/s1b"].activeChildren.filter( - (x) => x.componentName, - )[0].componentName; - let s1bGrandChildNames = stateVariables[ - s1bChildName - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(s1bGrandChildNames[0]).eq("/s1b/p1/n1"); - expect(s1bGrandChildNames[1]).eq("/s1b/p1/n2"); - expect(s1bGrandChildNames[2]).eq("/s1b/p1/n3"); - expect( - stateVariables[s1bGrandChildNames[0]].stateValues.value, - ).eq(1); - expect( - stateVariables[s1bGrandChildNames[1]].stateValues.value, - ).eq(2); - expect( - stateVariables[s1bGrandChildNames[2]].stateValues.value, - ).eq(3); - }); - }); - }); - - it("copy with newNamespace retains original names, even with group that assigns names, with copySource", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

values: 1 2 3

- -

- -

-

- -

-
- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - cy.get(cesc2("#/n1")).should("have.text", "1"); - cy.get(cesc2("#/n2")).should("have.text", "2"); - cy.get(cesc2("#/n3")).should("have.text", "3"); - - cy.get(cesc2("#/p1a/n1")).should("have.text", "1"); - cy.get(cesc2("#/p1a/n2")).should("have.text", "2"); - cy.get(cesc2("#/p1a/n3")).should("have.text", "3"); - - cy.get(cesc2("#/p1b/n1")).should("have.text", "1"); - cy.get(cesc2("#/p1b/n2")).should("have.text", "2"); - cy.get(cesc2("#/p1b/n3")).should("have.text", "3"); - - cy.get(cesc2("#/p1c/n1")).should("have.text", "1"); - cy.get(cesc2("#/p1c/n2")).should("have.text", "2"); - cy.get(cesc2("#/p1c/n3")).should("have.text", "3"); - - cy.get(cesc2("#/s1b/p1a/n1")).should("have.text", "1"); - cy.get(cesc2("#/s1b/p1a/n2")).should("have.text", "2"); - cy.get(cesc2("#/s1b/p1a/n3")).should("have.text", "3"); - - cy.get(cesc2("#/_p1")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/p1a")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/p1b")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/p1c")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/s1b/p1a")).should("have.text", "values: 1 2 3"); - - cy.get(cesc2("#/_section1")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 1\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#/s1a")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 2\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#/s1b")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 3\s*values: 1 2 3/)).not.be.null; - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/p1a/n1"].stateValues.value).eq(1); - expect(stateVariables["/p1a/n2"].stateValues.value).eq(2); - expect(stateVariables["/p1a/n3"].stateValues.value).eq(3); - - expect(stateVariables["/p1b/n1"].stateValues.value).eq(1); - expect(stateVariables["/p1b/n2"].stateValues.value).eq(2); - expect(stateVariables["/p1b/n3"].stateValues.value).eq(3); - - expect(stateVariables["/p1c/n1"].stateValues.value).eq(1); - expect(stateVariables["/p1c/n2"].stateValues.value).eq(2); - expect(stateVariables["/p1c/n3"].stateValues.value).eq(3); - - // s1a's grandchildren should have gotten unique names (so begin with two underscores) - let s1aChildName = - stateVariables["/s1a"].activeChildren[0].componentName; - let s1aGrandChildNames = stateVariables[s1aChildName].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - expect(s1aGrandChildNames[0].slice(0, 3)).eq("/__"); - expect(s1aGrandChildNames[1].slice(0, 3)).eq("/__"); - expect(s1aGrandChildNames[2].slice(0, 3)).eq("/__"); - expect(stateVariables[s1aGrandChildNames[0]].stateValues.value).eq( - 1, - ); - expect(stateVariables[s1aGrandChildNames[1]].stateValues.value).eq( - 2, - ); - expect(stateVariables[s1aGrandChildNames[2]].stateValues.value).eq( - 3, - ); - }); - }); - - it("copy with newNamespace and name retains original names, even with group that assigns name to just one number, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

values: 1 2 3

- -
$_p1{newNamespace name="p1"}
- - $p1 - $p1{name="p1a"} - $p1{newNamespace} - $p1{newNamespace name="p1b"} - $p1a{newNamespace} - - $_section1 - $_section1{name="s1a"} - $_section1{newNamespace} - $_section1{newNamespace name="s1b"} - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - cy.get(cesc2("#/n1")).should("have.text", "1"); - cy.get(cesc2("#/_number2")).should("have.text", "2"); - cy.get(cesc2("#/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/p1/n1")).should("have.text", "1"); - cy.get(cesc2("#/p1/_number2")).should("have.text", "2"); - cy.get(cesc2("#/p1/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/p1a/n1")).should("have.text", "1"); - cy.get(cesc2("#/p1a/_number2")).should("have.text", "2"); - cy.get(cesc2("#/p1a/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/p1b/n1")).should("have.text", "1"); - cy.get(cesc2("#/p1b/_number2")).should("have.text", "2"); - cy.get(cesc2("#/p1b/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/s1b/p1/n1")).should("have.text", "1"); - cy.get(cesc2("#/s1b/p1/_number2")).should("have.text", "2"); - cy.get(cesc2("#/s1b/p1/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/_p1")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/p1a")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/p1b")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/s1b/p1")).should("have.text", "values: 1 2 3"); - - cy.get(cesc2("#/_section1")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 1\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#/s1a")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 3\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#/s1b")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 5\s*values: 1 2 3/)).not.be.null; - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let c2p = - stateVariables["/_document1"].activeChildren[6].componentName; - let c4p = - stateVariables["/_document1"].activeChildren[10].componentName; - let c6p = - stateVariables["/_document1"].activeChildren[14].componentName; - let c7s = - stateVariables["/_document1"].activeChildren[16].componentName; - let c9s = - stateVariables["/_document1"].activeChildren[20].componentName; - - cy.get(cesc2("#" + c2p)).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#" + c4p)).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#" + c6p)).should("have.text", "values: 1 2 3"); - - cy.get(cesc2("#" + c7s)) - .invoke("text") - .then((text) => { - expect(text.match(/Section 2\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#" + c9s)) - .invoke("text") - .then((text) => { - expect(text.match(/Section 4\s*values: 1 2 3/)).not.be.null; - }); - - // put in window just so happens after above - cy.window().then(async (win) => { - expect(stateVariables["/p1/n1"].stateValues.value).eq(1); - expect(stateVariables["/p1/_number2"].stateValues.value).eq(2); - expect(stateVariables["/p1/_number3"].stateValues.value).eq(3); - - // c2p's children should have gotten unique names (so begin with two underscores) - let c2pChildNames = stateVariables[c2p].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - expect(c2pChildNames[0].slice(0, 3)).eq("/__"); - expect(c2pChildNames[1].slice(0, 3)).eq("/__"); - expect(c2pChildNames[2].slice(0, 3)).eq("/__"); - expect(stateVariables[c2pChildNames[0]].stateValues.value).eq( - 1, - ); - expect(stateVariables[c2pChildNames[1]].stateValues.value).eq( - 2, - ); - expect(stateVariables[c2pChildNames[2]].stateValues.value).eq( - 3, - ); - - // c4p's children should have gotten unique names (so begin with two underscores) - let c4pChildNames = stateVariables[c4p].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - expect(c4pChildNames[0].slice(0, 3)).eq("/__"); - expect(c4pChildNames[1].slice(0, 3)).eq("/__"); - expect(c4pChildNames[2].slice(0, 3)).eq("/__"); - expect(stateVariables[c4pChildNames[0]].stateValues.value).eq( - 1, - ); - expect(stateVariables[c4pChildNames[1]].stateValues.value).eq( - 2, - ); - expect(stateVariables[c4pChildNames[2]].stateValues.value).eq( - 3, - ); - - // c6p's children should have gotten unique names (so begin with two underscores) - let c6pChildNames = stateVariables[c6p].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - expect(c6pChildNames[0].slice(0, 3)).eq("/__"); - expect(c6pChildNames[1].slice(0, 3)).eq("/__"); - expect(c6pChildNames[2].slice(0, 3)).eq("/__"); - expect(stateVariables[c6pChildNames[0]].stateValues.value).eq( - 1, - ); - expect(stateVariables[c6pChildNames[1]].stateValues.value).eq( - 2, - ); - expect(stateVariables[c6pChildNames[2]].stateValues.value).eq( - 3, - ); - - // c7s's grandchildren should have gotten unique names (so begin with two underscores) - let c7sChildName = stateVariables[c7s].activeChildren.filter( - (x) => x.componentName, - )[0].componentName; - let c7sGrandChildNames = stateVariables[ - c7sChildName - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(c7sGrandChildNames[0].slice(0, 3)).eq("/__"); - expect(c7sGrandChildNames[1].slice(0, 3)).eq("/__"); - expect(c7sGrandChildNames[2].slice(0, 3)).eq("/__"); - expect( - stateVariables[c7sGrandChildNames[0]].stateValues.value, - ).eq(1); - expect( - stateVariables[c7sGrandChildNames[1]].stateValues.value, - ).eq(2); - expect( - stateVariables[c7sGrandChildNames[2]].stateValues.value, - ).eq(3); - - // s1a's grandchildren should have gotten unique names (so begin with two underscores) - let s1aChildName = stateVariables["/s1a"].activeChildren.filter( - (x) => x.componentName, - )[0].componentName; - let s1aGrandChildNames = stateVariables[ - s1aChildName - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(s1aGrandChildNames[0].slice(0, 3)).eq("/__"); - expect(s1aGrandChildNames[1].slice(0, 3)).eq("/__"); - expect(s1aGrandChildNames[2].slice(0, 3)).eq("/__"); - expect( - stateVariables[s1aGrandChildNames[0]].stateValues.value, - ).eq(1); - expect( - stateVariables[s1aGrandChildNames[1]].stateValues.value, - ).eq(2); - expect( - stateVariables[s1aGrandChildNames[2]].stateValues.value, - ).eq(3); - - // c9s's grandchildren should have gotten unique names (so begin with two underscores) - let c9sChildName = stateVariables[c9s].activeChildren.filter( - (x) => x.componentName, - )[0].componentName; - let c9sGrandChildNames = stateVariables[ - c9sChildName - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(c9sGrandChildNames[0].slice(0, 3)).eq("/__"); - expect(c9sGrandChildNames[1].slice(0, 3)).eq("/__"); - expect(c9sGrandChildNames[2].slice(0, 3)).eq("/__"); - expect( - stateVariables[c9sGrandChildNames[0]].stateValues.value, - ).eq(1); - expect( - stateVariables[c9sGrandChildNames[1]].stateValues.value, - ).eq(2); - expect( - stateVariables[c9sGrandChildNames[2]].stateValues.value, - ).eq(3); - - // s1b's grandchildren should have retained their original names - let s1bChildName = stateVariables["/s1b"].activeChildren.filter( - (x) => x.componentName, - )[0].componentName; - let s1bGrandChildNames = stateVariables[ - s1bChildName - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(s1bGrandChildNames[0]).eq("/s1b/p1/n1"); - expect(s1bGrandChildNames[1]).eq("/s1b/p1/_number2"); - expect(s1bGrandChildNames[2]).eq("/s1b/p1/_number3"); - expect( - stateVariables[s1bGrandChildNames[0]].stateValues.value, - ).eq(1); - expect( - stateVariables[s1bGrandChildNames[1]].stateValues.value, - ).eq(2); - expect( - stateVariables[s1bGrandChildNames[2]].stateValues.value, - ).eq(3); - }); - }); - }); - - it("copy with newNamespace and name retains original names, even with group that has new namespace, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

values: 1 2 3

- -
$_p1{newNamespace name="p1"}
- - $p1 - $p1{name="p1a"} - $p1{newNamespace} - $p1{newNamespace name="p1b"} - $p1a{newNamespace} - - $_section1 - $_section1{name="s1a"} - $_section1{newNamespace} - $_section1{newNamespace name="s1b"} - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - cy.get(cesc2("#/grp/_number1")).should("have.text", "1"); - cy.get(cesc2("#/grp/_number2")).should("have.text", "2"); - cy.get(cesc2("#/_number1")).should("have.text", "3"); - - cy.get(cesc2("#/p1/grp/_number1")).should("have.text", "1"); - cy.get(cesc2("#/p1/grp/_number2")).should("have.text", "2"); - cy.get(cesc2("#/p1/_number1")).should("have.text", "3"); - - cy.get(cesc2("#/p1a/grp/_number1")).should("have.text", "1"); - cy.get(cesc2("#/p1a/grp/_number2")).should("have.text", "2"); - cy.get(cesc2("#/p1a/_number1")).should("have.text", "3"); - - cy.get(cesc2("#/p1b/grp/_number1")).should("have.text", "1"); - cy.get(cesc2("#/p1b/grp/_number2")).should("have.text", "2"); - cy.get(cesc2("#/p1b/_number1")).should("have.text", "3"); - - cy.get(cesc2("#/s1b/p1/grp/_number1")).should("have.text", "1"); - cy.get(cesc2("#/s1b/p1/grp/_number2")).should("have.text", "2"); - cy.get(cesc2("#/s1b/p1/_number1")).should("have.text", "3"); - - cy.get(cesc2("#/_p1")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/p1a")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/p1b")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/s1b/p1")).should("have.text", "values: 1 2 3"); - - cy.get(cesc2("#/_section1")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 1\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#/s1a")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 3\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#/s1b")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 5\s*values: 1 2 3/)).not.be.null; - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let c2p = - stateVariables["/_document1"].activeChildren[6].componentName; - let c4p = - stateVariables["/_document1"].activeChildren[10].componentName; - let c6p = - stateVariables["/_document1"].activeChildren[14].componentName; - let c7s = - stateVariables["/_document1"].activeChildren[16].componentName; - let c9s = - stateVariables["/_document1"].activeChildren[20].componentName; - - cy.get(cesc2("#" + c2p)).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#" + c4p)).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#" + c6p)).should("have.text", "values: 1 2 3"); - - cy.get(cesc2("#" + c7s)) - .invoke("text") - .then((text) => { - expect(text.match(/Section 2\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#" + c9s)) - .invoke("text") - .then((text) => { - expect(text.match(/Section 4\s*values: 1 2 3/)).not.be.null; - }); - - // put in window just so happens after above - cy.window().then(async (win) => { - expect(stateVariables["/p1/grp/_number1"].stateValues.value).eq( - 1, - ); - expect(stateVariables["/p1/grp/_number2"].stateValues.value).eq( - 2, - ); - expect(stateVariables["/p1/_number1"].stateValues.value).eq(3); - - // c2p's children should have gotten unique names (so begin with two underscores) - let c2pChildNames = stateVariables[c2p].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - expect(c2pChildNames[0].slice(0, 3)).eq("/__"); - expect(c2pChildNames[1].slice(0, 3)).eq("/__"); - expect(c2pChildNames[2].slice(0, 3)).eq("/__"); - expect(stateVariables[c2pChildNames[0]].stateValues.value).eq( - 1, - ); - expect(stateVariables[c2pChildNames[1]].stateValues.value).eq( - 2, - ); - expect(stateVariables[c2pChildNames[2]].stateValues.value).eq( - 3, - ); - - // c4p's children should have gotten unique names (so begin with two underscores) - let c4pChildNames = stateVariables[c4p].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - expect(c4pChildNames[0].slice(0, 3)).eq("/__"); - expect(c4pChildNames[1].slice(0, 3)).eq("/__"); - expect(c4pChildNames[2].slice(0, 3)).eq("/__"); - expect(stateVariables[c4pChildNames[0]].stateValues.value).eq( - 1, - ); - expect(stateVariables[c4pChildNames[1]].stateValues.value).eq( - 2, - ); - expect(stateVariables[c4pChildNames[2]].stateValues.value).eq( - 3, - ); - - // c6p's children should have gotten unique names (so begin with two underscores) - let c6pChildNames = stateVariables[c6p].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - expect(c6pChildNames[0].slice(0, 3)).eq("/__"); - expect(c6pChildNames[1].slice(0, 3)).eq("/__"); - expect(c6pChildNames[2].slice(0, 3)).eq("/__"); - expect(stateVariables[c6pChildNames[0]].stateValues.value).eq( - 1, - ); - expect(stateVariables[c6pChildNames[1]].stateValues.value).eq( - 2, - ); - expect(stateVariables[c6pChildNames[2]].stateValues.value).eq( - 3, - ); - - // c7s's grandchildren should have gotten unique names (so begin with two underscores) - let c7sChildName = stateVariables[c7s].activeChildren.filter( - (x) => x.componentName, - )[0].componentName; - let c7sGrandChildNames = stateVariables[ - c7sChildName - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(c7sGrandChildNames[0].slice(0, 3)).eq("/__"); - expect(c7sGrandChildNames[1].slice(0, 3)).eq("/__"); - expect(c7sGrandChildNames[2].slice(0, 3)).eq("/__"); - expect( - stateVariables[c7sGrandChildNames[0]].stateValues.value, - ).eq(1); - expect( - stateVariables[c7sGrandChildNames[1]].stateValues.value, - ).eq(2); - expect( - stateVariables[c7sGrandChildNames[2]].stateValues.value, - ).eq(3); - - // s1a's grandchildren should have gotten unique names (so begin with two underscores) - let s1aChildName = stateVariables["/s1a"].activeChildren.filter( - (x) => x.componentName, - )[0].componentName; - let s1aGrandChildNames = stateVariables[ - s1aChildName - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(s1aGrandChildNames[0].slice(0, 3)).eq("/__"); - expect(s1aGrandChildNames[1].slice(0, 3)).eq("/__"); - expect(s1aGrandChildNames[2].slice(0, 3)).eq("/__"); - expect( - stateVariables[s1aGrandChildNames[0]].stateValues.value, - ).eq(1); - expect( - stateVariables[s1aGrandChildNames[1]].stateValues.value, - ).eq(2); - expect( - stateVariables[s1aGrandChildNames[2]].stateValues.value, - ).eq(3); - - // c9s's grandchildren should have gotten unique names (so begin with two underscores) - let c9sChildName = stateVariables[c9s].activeChildren.filter( - (x) => x.componentName, - )[0].componentName; - let c9sGrandChildNames = stateVariables[ - c9sChildName - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(c9sGrandChildNames[0].slice(0, 3)).eq("/__"); - expect(c9sGrandChildNames[1].slice(0, 3)).eq("/__"); - expect(c9sGrandChildNames[2].slice(0, 3)).eq("/__"); - expect( - stateVariables[c9sGrandChildNames[0]].stateValues.value, - ).eq(1); - expect( - stateVariables[c9sGrandChildNames[1]].stateValues.value, - ).eq(2); - expect( - stateVariables[c9sGrandChildNames[2]].stateValues.value, - ).eq(3); - - // s1b's grandchildren should have retained their original names - let s1bChildName = stateVariables["/s1b"].activeChildren.filter( - (x) => x.componentName, - )[0].componentName; - let s1bGrandChildNames = stateVariables[ - s1bChildName - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(s1bGrandChildNames[0]).eq("/s1b/p1/grp/_number1"); - expect(s1bGrandChildNames[1]).eq("/s1b/p1/grp/_number2"); - expect(s1bGrandChildNames[2]).eq("/s1b/p1/_number1"); - expect( - stateVariables[s1bGrandChildNames[0]].stateValues.value, - ).eq(1); - expect( - stateVariables[s1bGrandChildNames[1]].stateValues.value, - ).eq(2); - expect( - stateVariables[s1bGrandChildNames[2]].stateValues.value, - ).eq(3); - }); - }); - }); - - it("copy with newNamespace retains original names, even with group that has new namespace, with copySource", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

values: 1 2 3

- -

- -

-

- -

-
- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - cy.get(cesc2("#/grp/_number1")).should("have.text", "1"); - cy.get(cesc2("#/grp/_number2")).should("have.text", "2"); - cy.get(cesc2("#/_number1")).should("have.text", "3"); - - cy.get(cesc2("#/p1a/grp/_number1")).should("have.text", "1"); - cy.get(cesc2("#/p1a/grp/_number2")).should("have.text", "2"); - cy.get(cesc2("#/p1a/_number1")).should("have.text", "3"); - - cy.get(cesc2("#/p1b/grp/_number1")).should("have.text", "1"); - cy.get(cesc2("#/p1b/grp/_number2")).should("have.text", "2"); - cy.get(cesc2("#/p1b/_number1")).should("have.text", "3"); - - cy.get(cesc2("#/p1c/grp/_number1")).should("have.text", "1"); - cy.get(cesc2("#/p1c/grp/_number2")).should("have.text", "2"); - cy.get(cesc2("#/p1c/_number1")).should("have.text", "3"); - - cy.get(cesc2("#/_p1")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/p1a")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/p1b")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/p1c")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/s1b/p1a")).should("have.text", "values: 1 2 3"); - - cy.get(cesc2("#/_section1")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 1\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#/s1a")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 2\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#/s1b")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 3\s*values: 1 2 3/)).not.be.null; - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/p1a/grp/_number1"].stateValues.value).eq(1); - expect(stateVariables["/p1a/grp/_number2"].stateValues.value).eq(2); - expect(stateVariables["/p1a/_number1"].stateValues.value).eq(3); - - expect(stateVariables["/p1b/grp/_number1"].stateValues.value).eq(1); - expect(stateVariables["/p1b/grp/_number2"].stateValues.value).eq(2); - expect(stateVariables["/p1b/_number1"].stateValues.value).eq(3); - - expect(stateVariables["/p1c/grp/_number1"].stateValues.value).eq(1); - expect(stateVariables["/p1c/grp/_number2"].stateValues.value).eq(2); - expect(stateVariables["/p1c/_number1"].stateValues.value).eq(3); - - // s1a's grandchildren should have gotten unique names (so begin with two underscores) - let s1aChildName = - stateVariables["/s1a"].activeChildren[0].componentName; - let s1aGrandChildNames = stateVariables[s1aChildName].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - expect(s1aGrandChildNames[0].slice(0, 3)).eq("/__"); - expect(s1aGrandChildNames[1].slice(0, 3)).eq("/__"); - expect(s1aGrandChildNames[2].slice(0, 3)).eq("/__"); - expect(stateVariables[s1aGrandChildNames[0]].stateValues.value).eq( - 1, - ); - expect(stateVariables[s1aGrandChildNames[1]].stateValues.value).eq( - 2, - ); - expect(stateVariables[s1aGrandChildNames[2]].stateValues.value).eq( - 3, - ); - }); - }); - - it("copy with newNamespace and name retains original names, even with group that has new namespace and assigns names, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

values: 1 2 3

- -
$_p1{newNamespace name="p1"}
- - $p1 - $p1{name="p1a"} - $p1{newNamespace} - $p1{newNamespace name="p1b"} - $p1a{newNamespace} - - $_section1 - $_section1{name="s1a"} - $_section1{newNamespace} - $_section1{newNamespace name="s1b"} - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - cy.get(cesc2("#/grp/n1")).should("have.text", "1"); - cy.get(cesc2("#/grp/n2")).should("have.text", "2"); - cy.get(cesc2("#/n1")).should("have.text", "3"); - - cy.get(cesc2("#/p1/grp/n1")).should("have.text", "1"); - cy.get(cesc2("#/p1/grp/n2")).should("have.text", "2"); - cy.get(cesc2("#/p1/n1")).should("have.text", "3"); - - cy.get(cesc2("#/p1a/grp/n1")).should("have.text", "1"); - cy.get(cesc2("#/p1a/grp/n2")).should("have.text", "2"); - cy.get(cesc2("#/p1a/n1")).should("have.text", "3"); - - cy.get(cesc2("#/p1b/grp/n1")).should("have.text", "1"); - cy.get(cesc2("#/p1b/grp/n2")).should("have.text", "2"); - cy.get(cesc2("#/p1b/n1")).should("have.text", "3"); - - cy.get(cesc2("#/s1b/p1/grp/n1")).should("have.text", "1"); - cy.get(cesc2("#/s1b/p1/grp/n2")).should("have.text", "2"); - cy.get(cesc2("#/s1b/p1/n1")).should("have.text", "3"); - - cy.get(cesc2("#/_p1")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/p1a")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/p1b")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/s1b/p1")).should("have.text", "values: 1 2 3"); - - cy.get(cesc2("#/_section1")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 1\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#/s1a")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 3\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#/s1b")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 5\s*values: 1 2 3/)).not.be.null; - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let c2p = - stateVariables["/_document1"].activeChildren[6].componentName; - let c4p = - stateVariables["/_document1"].activeChildren[10].componentName; - let c6p = - stateVariables["/_document1"].activeChildren[14].componentName; - let c7s = - stateVariables["/_document1"].activeChildren[16].componentName; - let c9s = - stateVariables["/_document1"].activeChildren[20].componentName; - - cy.get(cesc2("#" + c2p)).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#" + c4p)).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#" + c6p)).should("have.text", "values: 1 2 3"); - - cy.get(cesc2("#" + c7s)) - .invoke("text") - .then((text) => { - expect(text.match(/Section 2\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#" + c9s)) - .invoke("text") - .then((text) => { - expect(text.match(/Section 4\s*values: 1 2 3/)).not.be.null; - }); - - // put in window just so happens after above - cy.window().then(async (win) => { - expect(stateVariables["/p1/grp/n1"].stateValues.value).eq(1); - expect(stateVariables["/p1/grp/n2"].stateValues.value).eq(2); - expect(stateVariables["/p1/n1"].stateValues.value).eq(3); - - // c2p's children should have gotten unique names (so begin with two underscores) - let c2pChildNames = stateVariables[c2p].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - expect(c2pChildNames[0].slice(0, 3)).eq("/__"); - expect(c2pChildNames[1].slice(0, 3)).eq("/__"); - expect(c2pChildNames[2].slice(0, 3)).eq("/__"); - expect(stateVariables[c2pChildNames[0]].stateValues.value).eq( - 1, - ); - expect(stateVariables[c2pChildNames[1]].stateValues.value).eq( - 2, - ); - expect(stateVariables[c2pChildNames[2]].stateValues.value).eq( - 3, - ); - - // c4p's children should have gotten unique names (so begin with two underscores) - let c4pChildNames = stateVariables[c4p].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - expect(c4pChildNames[0].slice(0, 3)).eq("/__"); - expect(c4pChildNames[1].slice(0, 3)).eq("/__"); - expect(c4pChildNames[2].slice(0, 3)).eq("/__"); - expect(stateVariables[c4pChildNames[0]].stateValues.value).eq( - 1, - ); - expect(stateVariables[c4pChildNames[1]].stateValues.value).eq( - 2, - ); - expect(stateVariables[c4pChildNames[2]].stateValues.value).eq( - 3, - ); - - // c6p's children should have gotten unique names (so begin with two underscores) - let c6pChildNames = stateVariables[c6p].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - expect(c6pChildNames[0].slice(0, 3)).eq("/__"); - expect(c6pChildNames[1].slice(0, 3)).eq("/__"); - expect(c6pChildNames[2].slice(0, 3)).eq("/__"); - expect(stateVariables[c6pChildNames[0]].stateValues.value).eq( - 1, - ); - expect(stateVariables[c6pChildNames[1]].stateValues.value).eq( - 2, - ); - expect(stateVariables[c6pChildNames[2]].stateValues.value).eq( - 3, - ); - - // c7s's grandchildren should have gotten unique names (so begin with two underscores) - let c7sChildName = stateVariables[c7s].activeChildren.filter( - (x) => x.componentName, - )[0].componentName; - let c7sGrandChildNames = stateVariables[ - c7sChildName - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(c7sGrandChildNames[0].slice(0, 3)).eq("/__"); - expect(c7sGrandChildNames[1].slice(0, 3)).eq("/__"); - expect(c7sGrandChildNames[2].slice(0, 3)).eq("/__"); - expect( - stateVariables[c7sGrandChildNames[0]].stateValues.value, - ).eq(1); - expect( - stateVariables[c7sGrandChildNames[1]].stateValues.value, - ).eq(2); - expect( - stateVariables[c7sGrandChildNames[2]].stateValues.value, - ).eq(3); - - // s1a's grandchildren should have gotten unique names (so begin with two underscores) - let s1aChildName = stateVariables["/s1a"].activeChildren.filter( - (x) => x.componentName, - )[0].componentName; - let s1aGrandChildNames = stateVariables[ - s1aChildName - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(s1aGrandChildNames[0].slice(0, 3)).eq("/__"); - expect(s1aGrandChildNames[1].slice(0, 3)).eq("/__"); - expect(s1aGrandChildNames[2].slice(0, 3)).eq("/__"); - expect( - stateVariables[s1aGrandChildNames[0]].stateValues.value, - ).eq(1); - expect( - stateVariables[s1aGrandChildNames[1]].stateValues.value, - ).eq(2); - expect( - stateVariables[s1aGrandChildNames[2]].stateValues.value, - ).eq(3); - - // c9s's grandchildren should have gotten unique names (so begin with two underscores) - let c9sChildName = stateVariables[c9s].activeChildren.filter( - (x) => x.componentName, - )[0].componentName; - let c9sGrandChildNames = stateVariables[ - c9sChildName - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(c9sGrandChildNames[0].slice(0, 3)).eq("/__"); - expect(c9sGrandChildNames[1].slice(0, 3)).eq("/__"); - expect(c9sGrandChildNames[2].slice(0, 3)).eq("/__"); - expect( - stateVariables[c9sGrandChildNames[0]].stateValues.value, - ).eq(1); - expect( - stateVariables[c9sGrandChildNames[1]].stateValues.value, - ).eq(2); - expect( - stateVariables[c9sGrandChildNames[2]].stateValues.value, - ).eq(3); - - // s1b's grandchildren should have retained their original names - let s1bChildName = stateVariables["/s1b"].activeChildren.filter( - (x) => x.componentName, - )[0].componentName; - let s1bGrandChildNames = stateVariables[ - s1bChildName - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(s1bGrandChildNames[0]).eq("/s1b/p1/grp/n1"); - expect(s1bGrandChildNames[1]).eq("/s1b/p1/grp/n2"); - expect(s1bGrandChildNames[2]).eq("/s1b/p1/n1"); - expect( - stateVariables[s1bGrandChildNames[0]].stateValues.value, - ).eq(1); - expect( - stateVariables[s1bGrandChildNames[1]].stateValues.value, - ).eq(2); - expect( - stateVariables[s1bGrandChildNames[2]].stateValues.value, - ).eq(3); - }); - }); - }); - - it("copy with newNamespace retains original names, even with group that has new namespace and assigns names, with copySource", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

values: 1 2 3

- -

- -

-

- -

-
- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - cy.get(cesc2("#/grp/n1")).should("have.text", "1"); - cy.get(cesc2("#/grp/n2")).should("have.text", "2"); - cy.get(cesc2("#/n1")).should("have.text", "3"); - - cy.get(cesc2("#/p1a/grp/n1")).should("have.text", "1"); - cy.get(cesc2("#/p1a/grp/n2")).should("have.text", "2"); - cy.get(cesc2("#/p1a/n1")).should("have.text", "3"); - - cy.get(cesc2("#/p1b/grp/n1")).should("have.text", "1"); - cy.get(cesc2("#/p1b/grp/n2")).should("have.text", "2"); - cy.get(cesc2("#/p1b/n1")).should("have.text", "3"); - - cy.get(cesc2("#/p1c/grp/n1")).should("have.text", "1"); - cy.get(cesc2("#/p1c/grp/n2")).should("have.text", "2"); - cy.get(cesc2("#/p1c/n1")).should("have.text", "3"); - - cy.get(cesc2("#/_p1")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/p1a")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/p1b")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/p1c")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/s1b/p1a")).should("have.text", "values: 1 2 3"); - - cy.get(cesc2("#/_section1")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 1\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#/s1a")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 2\s*values: 1 2 3/)).not.be.null; - }); - cy.get(cesc2("#/s1b")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 3\s*values: 1 2 3/)).not.be.null; - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/p1a/grp/n1"].stateValues.value).eq(1); - expect(stateVariables["/p1a/grp/n2"].stateValues.value).eq(2); - expect(stateVariables["/p1a/n1"].stateValues.value).eq(3); - - expect(stateVariables["/p1b/grp/n1"].stateValues.value).eq(1); - expect(stateVariables["/p1b/grp/n2"].stateValues.value).eq(2); - expect(stateVariables["/p1b/n1"].stateValues.value).eq(3); - - expect(stateVariables["/p1c/grp/n1"].stateValues.value).eq(1); - expect(stateVariables["/p1c/grp/n2"].stateValues.value).eq(2); - expect(stateVariables["/p1c/n1"].stateValues.value).eq(3); - - // s1a's grandchildren should have gotten unique names (so begin with two underscores) - let s1aChildName = - stateVariables["/s1a"].activeChildren[0].componentName; - let s1aGrandChildNames = stateVariables[s1aChildName].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - expect(s1aGrandChildNames[0].slice(0, 3)).eq("/__"); - expect(s1aGrandChildNames[1].slice(0, 3)).eq("/__"); - expect(s1aGrandChildNames[2].slice(0, 3)).eq("/__"); - expect(stateVariables[s1aGrandChildNames[0]].stateValues.value).eq( - 1, - ); - expect(stateVariables[s1aGrandChildNames[1]].stateValues.value).eq( - 2, - ); - expect(stateVariables[s1aGrandChildNames[2]].stateValues.value).eq( - 3, - ); - }); - }); - - it("copy with newNamespace and name retains original names, even with group, wrapped in nested groups and copied with variable componentIndex", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - -

values: 1 2 3

- -
$_p1{newNamespace name="p1"}
- - $p1{name="p1a"} - $p1{newNamespace name="p1b"} - - $_section1{newNamespace name="s1b"} -
- -

values: 4 5 6

- -
$_p1{newNamespace name="p1"}
- - $p1{name="p1a"} - $p1{newNamespace name="p1b"} - - $_section1{newNamespace name="s1b"} -
-
- - $grp[$n]{name="thegrp"} - - - `, - }, - "*", - ); - }); - - cy.log("check g1"); - cy.get(cesc2("#/g1/_number1")).should("have.text", "1"); - cy.get(cesc2("#/g1/_number2")).should("have.text", "2"); - cy.get(cesc2("#/g1/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/g1/p1/_number1")).should("have.text", "1"); - cy.get(cesc2("#/g1/p1/_number2")).should("have.text", "2"); - cy.get(cesc2("#/g1/p1/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/g1/p1a/_number1")).should("have.text", "1"); - cy.get(cesc2("#/g1/p1a/_number2")).should("have.text", "2"); - cy.get(cesc2("#/g1/p1a/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/g1/p1b/_number1")).should("have.text", "1"); - cy.get(cesc2("#/g1/p1b/_number2")).should("have.text", "2"); - cy.get(cesc2("#/g1/p1b/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/g1/s1b/p1/_number1")).should("have.text", "1"); - cy.get(cesc2("#/g1/s1b/p1/_number2")).should("have.text", "2"); - cy.get(cesc2("#/g1/s1b/p1/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/g1/_p1")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/g1/p1a")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/g1/p1b")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/g1/s1b/p1")).should("have.text", "values: 1 2 3"); - - cy.get(cesc2("#/g1/_section1")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 1\s*values: 1 2 3/)).not.be.null; - }); - - cy.get(cesc2("#/g1/s1b")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 2\s*values: 1 2 3/)).not.be.null; - }); - - cy.log("check g2"); - - cy.get(cesc2("#/g2/n1")).should("have.text", "4"); - cy.get(cesc2("#/g2/n2")).should("have.text", "5"); - cy.get(cesc2("#/g2/n3")).should("have.text", "6"); - - cy.get(cesc2("#/g2/p1/n1")).should("have.text", "4"); - cy.get(cesc2("#/g2/p1/n2")).should("have.text", "5"); - cy.get(cesc2("#/g2/p1/n3")).should("have.text", "6"); - - cy.get(cesc2("#/g2/p1a/n1")).should("have.text", "4"); - cy.get(cesc2("#/g2/p1a/n2")).should("have.text", "5"); - cy.get(cesc2("#/g2/p1a/n3")).should("have.text", "6"); - - cy.get(cesc2("#/g2/p1b/n1")).should("have.text", "4"); - cy.get(cesc2("#/g2/p1b/n2")).should("have.text", "5"); - cy.get(cesc2("#/g2/p1b/n3")).should("have.text", "6"); - - cy.get(cesc2("#/g2/s1b/p1/n1")).should("have.text", "4"); - cy.get(cesc2("#/g2/s1b/p1/n2")).should("have.text", "5"); - cy.get(cesc2("#/g2/s1b/p1/n3")).should("have.text", "6"); - - cy.get(cesc2("#/g2/_p1")).should("have.text", "values: 4 5 6"); - cy.get(cesc2("#/g2/p1a")).should("have.text", "values: 4 5 6"); - cy.get(cesc2("#/g2/p1b")).should("have.text", "values: 4 5 6"); - cy.get(cesc2("#/g2/s1b/p1")).should("have.text", "values: 4 5 6"); - - cy.get(cesc2("#/g2/_section1")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 3\s*values: 4 5 6/)).not.be.null; - }); - - cy.get(cesc2("#/g2/s1b")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 4\s*values: 4 5 6/)).not.be.null; - }); - - cy.log("check thegrp"); - - cy.get(cesc2("#/thegrp/_number1")).should("have.text", "1"); - cy.get(cesc2("#/thegrp/_number2")).should("have.text", "2"); - cy.get(cesc2("#/thegrp/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/thegrp/p1/_number1")).should("have.text", "1"); - cy.get(cesc2("#/thegrp/p1/_number2")).should("have.text", "2"); - cy.get(cesc2("#/thegrp/p1/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/thegrp/p1a/_number1")).should("have.text", "1"); - cy.get(cesc2("#/thegrp/p1a/_number2")).should("have.text", "2"); - cy.get(cesc2("#/thegrp/p1a/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/thegrp/p1b/_number1")).should("have.text", "1"); - cy.get(cesc2("#/thegrp/p1b/_number2")).should("have.text", "2"); - cy.get(cesc2("#/thegrp/p1b/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/thegrp/s1b/p1/_number1")).should("have.text", "1"); - cy.get(cesc2("#/thegrp/s1b/p1/_number2")).should("have.text", "2"); - cy.get(cesc2("#/thegrp/s1b/p1/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/thegrp/_p1")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/thegrp/p1a")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/thegrp/p1b")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/thegrp/s1b/p1")).should("have.text", "values: 1 2 3"); - - cy.get(cesc2("#/thegrp/_section1")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 5\s*values: 1 2 3/)).not.be.null; - }); - - cy.get(cesc2("#/thegrp/s1b")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 6\s*values: 1 2 3/)).not.be.null; - }); - - cy.log("Change index for thegrp"); - cy.get(cesc2("#/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - - cy.get(cesc2("#/thegrp/n1")).should("have.text", "4"); - cy.get(cesc2("#/thegrp/n2")).should("have.text", "5"); - cy.get(cesc2("#/thegrp/n3")).should("have.text", "6"); - - cy.get(cesc2("#/thegrp/p1/n1")).should("have.text", "4"); - cy.get(cesc2("#/thegrp/p1/n2")).should("have.text", "5"); - cy.get(cesc2("#/thegrp/p1/n3")).should("have.text", "6"); - - cy.get(cesc2("#/thegrp/p1a/n1")).should("have.text", "4"); - cy.get(cesc2("#/thegrp/p1a/n2")).should("have.text", "5"); - cy.get(cesc2("#/thegrp/p1a/n3")).should("have.text", "6"); - - cy.get(cesc2("#/thegrp/p1b/n1")).should("have.text", "4"); - cy.get(cesc2("#/thegrp/p1b/n2")).should("have.text", "5"); - cy.get(cesc2("#/thegrp/p1b/n3")).should("have.text", "6"); - - cy.get(cesc2("#/thegrp/s1b/p1/n1")).should("have.text", "4"); - cy.get(cesc2("#/thegrp/s1b/p1/n2")).should("have.text", "5"); - cy.get(cesc2("#/thegrp/s1b/p1/n3")).should("have.text", "6"); - - cy.get(cesc2("#/thegrp/_p1")).should("have.text", "values: 4 5 6"); - cy.get(cesc2("#/thegrp/p1a")).should("have.text", "values: 4 5 6"); - cy.get(cesc2("#/thegrp/p1b")).should("have.text", "values: 4 5 6"); - cy.get(cesc2("#/thegrp/s1b/p1")).should("have.text", "values: 4 5 6"); - - cy.get(cesc2("#/thegrp/_section1")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 5\s*values: 4 5 6/)).not.be.null; - }); - - cy.get(cesc2("#/thegrp/s1b")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 6\s*values: 4 5 6/)).not.be.null; - }); - - cy.log("Change to invalid index for thegrp"); - cy.get(cesc2("#/n") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - cy.get(cesc2("#/thegrp")).should("not.exist"); - - cy.log("Change back to index 1 for thegrp"); - cy.get(cesc2("#/n") + " textarea").type("{end}{backspace}1{enter}", { - force: true, - }); - - cy.get(cesc2("#/thegrp/_number1")).should("have.text", "1"); - cy.get(cesc2("#/thegrp/_number2")).should("have.text", "2"); - cy.get(cesc2("#/thegrp/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/thegrp/p1/_number1")).should("have.text", "1"); - cy.get(cesc2("#/thegrp/p1/_number2")).should("have.text", "2"); - cy.get(cesc2("#/thegrp/p1/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/thegrp/p1a/_number1")).should("have.text", "1"); - cy.get(cesc2("#/thegrp/p1a/_number2")).should("have.text", "2"); - cy.get(cesc2("#/thegrp/p1a/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/thegrp/p1b/_number1")).should("have.text", "1"); - cy.get(cesc2("#/thegrp/p1b/_number2")).should("have.text", "2"); - cy.get(cesc2("#/thegrp/p1b/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/thegrp/s1b/p1/_number1")).should("have.text", "1"); - cy.get(cesc2("#/thegrp/s1b/p1/_number2")).should("have.text", "2"); - cy.get(cesc2("#/thegrp/s1b/p1/_number3")).should("have.text", "3"); - - cy.get(cesc2("#/thegrp/_p1")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/thegrp/p1a")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/thegrp/p1b")).should("have.text", "values: 1 2 3"); - cy.get(cesc2("#/thegrp/s1b/p1")).should("have.text", "values: 1 2 3"); - - cy.get(cesc2("#/thegrp/_section1")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 5\s*values: 1 2 3/)).not.be.null; - }); - - cy.get(cesc2("#/thegrp/s1b")) - .invoke("text") - .then((text) => { - expect(text.match(/Section 6\s*values: 1 2 3/)).not.be.null; - }); - }); - - it("copy group of groups retains name", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 1 2 3456 - - $grp{name="grp2"} - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/grp/num1")).should("have.text", "1"); - cy.get(cesc2("#/grp/num2")).should("have.text", "2"); - cy.get(cesc2("#/grp/num3")).should("have.text", "3"); - cy.get(cesc2("#/grp/num4")).should("have.text", "4"); - cy.get(cesc2("#/grp/num5")).should("have.text", "5"); - cy.get(cesc2("#/grp/num6")).should("have.text", "6"); - - cy.get(cesc2("#/grp2/num1")).should("have.text", "1"); - cy.get(cesc2("#/grp2/num2")).should("have.text", "2"); - cy.get(cesc2("#/grp2/num3")).should("have.text", "3"); - cy.get(cesc2("#/grp2/num4")).should("have.text", "4"); - cy.get(cesc2("#/grp2/num5")).should("have.text", "5"); - cy.get(cesc2("#/grp2/num6")).should("have.text", "6"); - - cy.get(cesc2("#/grp3/num1")).should("have.text", "1"); - cy.get(cesc2("#/grp3/num2")).should("have.text", "2"); - cy.get(cesc2("#/grp3/num3")).should("have.text", "3"); - cy.get(cesc2("#/grp3/num4")).should("have.text", "4"); - cy.get(cesc2("#/grp3/num5")).should("have.text", "5"); - cy.get(cesc2("#/grp3/num6")).should("have.text", "6"); - - cy.get(cesc2("#/grp4/num3")).should("have.text", "3"); - cy.get(cesc2("#/grp4/num4")).should("have.text", "4"); - cy.get(cesc2("#/grp4/num5")).should("have.text", "5"); - cy.get(cesc2("#/grp4/num6")).should("have.text", "6"); - - cy.get(cesc2("#/grp5/num3")).should("have.text", "3"); - cy.get(cesc2("#/grp5/num4")).should("have.text", "4"); - cy.get(cesc2("#/grp5/num5")).should("have.text", "5"); - cy.get(cesc2("#/grp5/num6")).should("have.text", "6"); - }); - - it("copy group, does not avoid name collision when assign subnames", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 2 - -

$grp{assignNames="num2"}

- - - `, - }, - "*", - ); - }); - - cy.document().should("contain.text", "Duplicate component name: num2"); - }); - - it("copy p with newNamespace, does not avoid name collision when assignnames", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

Hello

- $p{newNamespace name="hello"} - - `, - }, - "*", - ); - }); - - cy.document().should("contain.text", "Duplicate component name: hello"); - }); - - it("copy point with math attribute, duplicate component name message uses point name", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - $P{name="P" y="2" } - `, - }, - "*", - ); - }); - - cy.document().should("contain.text", "Duplicate component name: P"); - }); - - it("copy componentIndex", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

n:

- - - (1,2) - (3,4) - - - - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let x1 = 1, - y1 = 2, - x2 = 3, - y2 = 4; - - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/A2"]).eq(undefined); - expect(stateVariables["/g3/A2"]).eq(undefined); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/Ax"]).eq(undefined); - expect(stateVariables["/al2/Ax"]).eq(undefined); - }); - - cy.log("restrict collection to first component"); - - cy.get(cesc("#\\/n") + " textarea").type("1{enter}", { force: true }); - - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/A2"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/g3/A2"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/Ax"].stateValues.value).eq(x1); - expect(stateVariables["/al2/Ax"].stateValues.value).eq(x1); - }); - - cy.log("move copied point"); - cy.window().then(async (win) => { - (x1 = 9), (y1 = -5); - await win.callAction1({ - actionName: "movePoint", - componentName: "/A2", - args: { x: x1, y: y1 }, - }); - - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/A2"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/g3/A2"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/Ax"].stateValues.value).eq(x1); - expect(stateVariables["/al2/Ax"].stateValues.value).eq(x1); - }); - }); - - cy.log("collect second component"); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/A2"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/g3/A2"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/Ax"].stateValues.value).eq(x2); - expect(stateVariables["/al2/Ax"].stateValues.value).eq(x2); - }); - }); - - cy.log("move double copied point"); - cy.window().then(async (win) => { - (x2 = 0), (y2 = 8); - await win.callAction1({ - actionName: "movePoint", - componentName: "/g3/A2", - args: { x: x2, y: y2 }, - }); - - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/A2"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/g3/A2"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/Ax"].stateValues.value).eq(x2); - expect(stateVariables["/al2/Ax"].stateValues.value).eq(x2); - }); - }); - }); - - it("copy componentIndex, array notation", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

n:

- - - (1,2) - (3,4) - - - - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let x1 = 1, - y1 = 2, - x2 = 3, - y2 = 4; - - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/A2"]).eq(undefined); - expect(stateVariables["/g3/A2"]).eq(undefined); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/Ax"]).eq(undefined); - expect(stateVariables["/al2/Ax"]).eq(undefined); - }); - - cy.log("restrict collection to first component"); - - cy.get(cesc("#\\/n") + " textarea").type("1{enter}", { force: true }); - - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/A2"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/g3/A2"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/Ax"].stateValues.value).eq(x1); - expect(stateVariables["/al2/Ax"].stateValues.value).eq(x1); - }); - - cy.log("move copied point"); - cy.window().then(async (win) => { - (x1 = 9), (y1 = -5); - await win.callAction1({ - actionName: "movePoint", - componentName: "/A2", - args: { x: x1, y: y1 }, - }); - - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/A2"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/g3/A2"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/Ax"].stateValues.value).eq(x1); - expect(stateVariables["/al2/Ax"].stateValues.value).eq(x1); - }); - }); - - cy.log("restrict collection to second component"); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/A2"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/g3/A2"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/Ax"].stateValues.value).eq(x2); - expect(stateVariables["/al2/Ax"].stateValues.value).eq(x2); - }); - }); - - cy.log("move double copied point"); - cy.window().then(async (win) => { - (x2 = 0), (y2 = 8); - await win.callAction1({ - actionName: "movePoint", - componentName: "/g3/A2", - args: { x: x2, y: y2 }, - }); - - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/A2"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/g3/A2"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/Ax"].stateValues.value).eq(x2); - expect(stateVariables["/al2/Ax"].stateValues.value).eq(x2); - }); - }); - }); - - it("copy componentIndex, array notation, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

n:

- - - (1,2) - (3,4) - - - - - - - - $(col[$n]{name="A2"}) - - - $g2{name="g3" newNamespace} - - $(col[$n].x{assignNames="Ax"}) - - $al{name="al2" newNamespace} - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let x1 = 1, - y1 = 2, - x2 = 3, - y2 = 4; - - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/A2"]).eq(undefined); - expect(stateVariables["/g3/A2"]).eq(undefined); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/Ax"]).eq(undefined); - expect(stateVariables["/al2/Ax"]).eq(undefined); - }); - - cy.log("restrict collection to first component"); - - cy.get(cesc("#\\/n") + " textarea").type("1{enter}", { force: true }); - - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/A2"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/g3/A2"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/Ax"].stateValues.value).eq(x1); - expect(stateVariables["/al2/Ax"].stateValues.value).eq(x1); - }); - - cy.log("move copied point"); - cy.window().then(async (win) => { - (x1 = 9), (y1 = -5); - await win.callAction1({ - actionName: "movePoint", - componentName: "/A2", - args: { x: x1, y: y1 }, - }); - - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/A2"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/g3/A2"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/Ax"].stateValues.value).eq(x1); - expect(stateVariables["/al2/Ax"].stateValues.value).eq(x1); - }); - }); - - cy.log("restrict collection to second component"); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/A2"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/g3/A2"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/Ax"].stateValues.value).eq(x2); - expect(stateVariables["/al2/Ax"].stateValues.value).eq(x2); - }); - }); - - cy.log("move double copied point"); - cy.window().then(async (win) => { - (x2 = 0), (y2 = 8); - await win.callAction1({ - actionName: "movePoint", - componentName: "/g3/A2", - args: { x: x2, y: y2 }, - }); - - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/A2"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/g3/A2"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/Ax"].stateValues.value).eq(x2); - expect(stateVariables["/al2/Ax"].stateValues.value).eq(x2); - }); - }); - }); - - it("copy componentIndex, with copySource", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

n:

- - - (1,2) - (3,4) - - - - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let x1 = 1, - y1 = 2, - x2 = 3, - y2 = 4; - - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/A2"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/g3/A2"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/Ax"].stateValues.value).eq(x1); - expect(stateVariables["/al2/Ax"].stateValues.value).eq(x1); - }); - - cy.log("move copied point"); - cy.window().then(async (win) => { - (x1 = 9), (y1 = -5); - await win.callAction1({ - actionName: "movePoint", - componentName: "/A2", - args: { x: x1, y: y1 }, - }); - - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/A2"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/g3/A2"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/Ax"].stateValues.value).eq(x1); - expect(stateVariables["/al2/Ax"].stateValues.value).eq(x1); - }); - }); - - cy.log("restrict collection to second component"); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/A2"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/g3/A2"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/Ax"].stateValues.value).eq(x2); - expect(stateVariables["/al2/Ax"].stateValues.value).eq(x2); - }); - }); - - cy.log("move double copied point"); - cy.window().then(async (win) => { - (x2 = 0), (y2 = 8); - await win.callAction1({ - actionName: "movePoint", - componentName: "/g3/A2", - args: { x: x2, y: y2 }, - }); - - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), + cy.log(`select incorrect answer for problem 1`).then(() => { + let incorrectInd = (problem1Version + 1) % 4; + let sound = soundOptions[incorrectInd]; + cy.get(cesc2("#/problem34/problem1/_choiceinput1")) + .contains(sound) + .click({ force: true }); + cy.get(cesc2("#/problem34/problem1/_choiceinput1_submit")).click(); + cy.get(cesc2("#/problem34/problem1/_choiceinput1_correct")).should( + "not.exist", ); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), + cy.get( + cesc2("#/problem34/problem1/_choiceinput1_incorrect"), + ).should("be.visible"); + cy.get(cesc2("#/problem34/problem1/_feedback1")).should( + "not.exist", ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/A2"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/g3/A2"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/Ax"].stateValues.value).eq(x2); - expect(stateVariables["/al2/Ax"].stateValues.value).eq(x2); - }); - }); - }); - - it("copy componentIndex, with copySource, array notation", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

n:

- - - (1,2) - (3,4) - - - - - - - - - - - - - - - - - `, - }, - "*", + cy.get(cesc2("#/problem34/problem1/_feedback2")).should( + "have.text", + `Try again.`, ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let x1 = 1, - y1 = 2, - x2 = 3, - y2 = 4; - - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), + cy.get(cesc2("#/problem34/problem2/_title1")).should( + "have.text", + "Derivative problem", ); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/A2"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/g3/A2"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/Ax"].stateValues.value).eq(x1); - expect(stateVariables["/al2/Ax"].stateValues.value).eq(x1); - }); - - cy.log("move copied point"); - cy.window().then(async (win) => { - (x1 = 9), (y1 = -5); - await win.callAction1({ - actionName: "movePoint", - componentName: "/A2", - args: { x: x1, y: y1 }, - }); - - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/A2"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/g3/A2"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/Ax"].stateValues.value).eq(x1); - expect(stateVariables["/al2/Ax"].stateValues.value).eq(x1); - }); - }); - - cy.log("restrict collection to second component"); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/A2"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/g3/A2"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/Ax"].stateValues.value).eq(x2); - expect(stateVariables["/al2/Ax"].stateValues.value).eq(x2); - }); - }); - - cy.log("move double copied point"); - cy.window().then(async (win) => { - (x2 = 0), (y2 = 8); - await win.callAction1({ - actionName: "movePoint", - componentName: "/g3/A2", - args: { x: x2, y: y2 }, - }); - - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), + let mathinputName = + stateVariables["/problem34/problem2/_answer1"].stateValues + .inputChildren[0].componentName; + let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; + let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); + let mathinputCorrectAnchor = cesc2( + "#" + mathinputName + "_correct", ); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), + let mathinputIncorrectAnchor = cesc2( + "#" + mathinputName + "_incorrect", ); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/A2"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/g3/A2"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/Ax"].stateValues.value).eq(x2); - expect(stateVariables["/al2/Ax"].stateValues.value).eq(x2); - }); + cy.log(`enter incorrect answer for problem 2`); + cy.get(mathinputAnchor).type("2y{enter}", { force: true }); + cy.get(mathinputSubmitAnchor).should("not.exist"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("be.visible"); + + cy.log(`enter correct answer for problem 2`); + cy.get(mathinputAnchor).type("{end}{backspace}x", { force: true }); + cy.get(mathinputSubmitAnchor).should("be.visible"); + cy.get(mathinputAnchor).type("{enter}", { force: true }); + cy.get(mathinputSubmitAnchor).should("not.exist"); + cy.get(mathinputCorrectAnchor).should("be.visible"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); }); }); - it("copy propIndex and componentIndex", () => { + // this triggered an error not caught with the other order + it("copy uri containing copy uri of two problems, newNamespace first", () => { cy.window().then(async (win) => { win.postMessage( { doenetML: ` - a - -

m:

-

n:

- - - (1,2) - (3,4) - + Four problems - - - - + -

- -

- + `, }, "*", ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let x1 = 1, - y1 = 2, - x2 = 3, - y2 = 4; - - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); - }); - - cy.log("set propIndex to 1"); - - cy.get(cesc("#\\/n") + " textarea").type("1{enter}", { force: true }); - - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); - }); - - cy.log("move point 1"); - cy.window().then(async (win) => { - (x1 = 9), (y1 = -5); - await win.callAction1({ - actionName: "movePoint", - componentName: "/A", - args: { x: x1, y: y1 }, - }); + cy.get(cesc("#\\/_title1")).should("have.text", "Four problems"); // to wait for page to load - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); + let problem1Version; + let animalOptions = ["cat", "dog", "mouse", "fish"]; + let soundOptions = ["meow", "woof", "squeak", "blub"]; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); + cy.get(cesc2("#/problem12/problem1/_p1")) + .invoke("text") + .then((text) => { + let titleOptions = animalOptions.map( + (x) => `What does the ${x} say?`, + ); + problem1Version = titleOptions.indexOf(text); + expect(problem1Version).not.eq(-1); }); - }); - - cy.log("set componentIndex to 2"); - cy.get(cesc("#\\/m") + " textarea").type("2{enter}", { force: true }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), + cy.log(`select correct answer for problem 1`).then(() => { + let animal = animalOptions[problem1Version]; + let sound = soundOptions[problem1Version]; + cy.get(cesc2("#/problem12/problem1/_choiceinput1")) + .contains(sound) + .click({ force: true }); + cy.get(cesc2("#/problem12/problem1/_choiceinput1_submit")).click(); + cy.get(cesc2("#/problem12/problem1/_choiceinput1_correct")).should( + "be.visible", ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(x2); - expect(stateVariables["/al2/n1"].stateValues.value).eq(x2); - }); - }); - - cy.log("move point2"); - cy.window().then(async (win) => { - (x2 = 0), (y2 = 8); - await win.callAction1({ - actionName: "movePoint", - componentName: "/B", - args: { x: x2, y: y2 }, - }); - - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), + cy.get( + cesc2("#/problem12/problem1/_choiceinput1_incorrect"), + ).should("not.exist"); + cy.get(cesc2("#/problem12/problem1/_feedback1")).should( + "have.text", + `That's right, the ${animal} goes ${sound}!`, ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), + cy.get(cesc2("#/problem12/problem1/_feedback2")).should( + "not.exist", ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(x2); - expect(stateVariables["/al2/n1"].stateValues.value).eq(x2); - }); - }); - - cy.log("set propIndex to 2"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, }); - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y2), - ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y2), + cy.log(`select incorrect answer for problem 1`).then(() => { + let incorrectInd = (problem1Version + 1) % 4; + let sound = soundOptions[incorrectInd]; + cy.get(cesc2("#/problem12/problem1/_choiceinput1")) + .contains(sound) + .click({ force: true }); + cy.get(cesc2("#/problem12/problem1/_choiceinput1_submit")).click(); + cy.get(cesc2("#/problem12/problem1/_choiceinput1_correct")).should( + "not.exist", ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(y2); - expect(stateVariables["/al2/n1"].stateValues.value).eq(y2); - }); - }); - - cy.log("set componentIndex to 1"); - cy.get(cesc("#\\/m") + " textarea").type("{end}{backspace}1{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y1), + cy.get( + cesc2("#/problem12/problem1/_choiceinput1_incorrect"), + ).should("be.visible"); + cy.get(cesc2("#/problem12/problem1/_feedback1")).should( + "not.exist", ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y1), + cy.get(cesc2("#/problem12/problem1/_feedback2")).should( + "have.text", + `Try again.`, ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(y1); - expect(stateVariables["/al2/n1"].stateValues.value).eq(y1); - }); - }); - - cy.log("set propIndex to 3"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); - }); }); - cy.log("set propIndex to 1"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}1{enter}", { - force: true, - }); + cy.get(cesc2("#/problem12/problem2/_title1")).should( + "have.text", + "Derivative problem", + ); cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), + let stateVariables = await win.returnAllStateVariables1(); + let mathinputName = + stateVariables["/problem12/problem2/_answer1"].stateValues + .inputChildren[0].componentName; + let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; + let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); + let mathinputCorrectAnchor = cesc2( + "#" + mathinputName + "_correct", ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), + let mathinputIncorrectAnchor = cesc2( + "#" + mathinputName + "_incorrect", ); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(x1); - expect(stateVariables["/al2/n1"].stateValues.value).eq(x1); - }); - }); - - cy.log("set componentIndex to 3"); - cy.get(cesc("#\\/m") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); - }); - }); + cy.log(`enter incorrect answer for problem 2`); + cy.get(mathinputAnchor).type("2y{enter}", { force: true }); + cy.get(mathinputSubmitAnchor).should("not.exist"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("be.visible"); - cy.log("set componentIndex to 2"); - cy.get(cesc("#\\/m") + " textarea").type("{end}{backspace}2{enter}", { - force: true, + cy.log(`enter correct answer for problem 2`); + cy.get(mathinputAnchor).type("{end}{backspace}x", { force: true }); + cy.get(mathinputSubmitAnchor).should("be.visible"); + cy.get(mathinputAnchor).type("{enter}", { force: true }); + cy.get(mathinputSubmitAnchor).should("not.exist"); + cy.get(mathinputCorrectAnchor).should("be.visible"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); }); - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(x2); - expect(stateVariables["/al2/n1"].stateValues.value).eq(x2); + cy.get(cesc2("#/problem34/problem1/_p1")) + .invoke("text") + .then((text) => { + let titleOptions = animalOptions.map( + (x) => `What does the ${x} say?`, + ); + problem1Version = titleOptions.indexOf(text); + expect(problem1Version).not.eq(-1); }); - }); - - cy.log("clear propIndex"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}{enter}", { - force: true, - }); - - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); - }); - }); - - it("copy propIndex and componentIndex, array notation", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

m:

-

n:

- - - (1,2) - (3,4) - - - - - - - -

-

- - `, - }, - "*", + cy.log(`select correct answer for problem 1`).then(() => { + let animal = animalOptions[problem1Version]; + let sound = soundOptions[problem1Version]; + cy.get(cesc2("#/problem34/problem1/_choiceinput1")) + .contains(sound) + .click({ force: true }); + cy.get(cesc2("#/problem34/problem1/_choiceinput1_submit")).click(); + cy.get(cesc2("#/problem34/problem1/_choiceinput1_correct")).should( + "be.visible", ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let x1 = 1, - y1 = 2, - x2 = 3, - y2 = 4; - - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); - }); - - cy.log("set propIndex to 1"); - - cy.get(cesc("#\\/n") + " textarea").type("1{enter}", { force: true }); - - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); - }); - - cy.log("move point 1"); - cy.window().then(async (win) => { - (x1 = 9), (y1 = -5); - await win.callAction1({ - actionName: "movePoint", - componentName: "/A", - args: { x: x1, y: y1 }, - }); - - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); - }); - }); - - cy.log("set componentIndex to 2"); - - cy.get(cesc("#\\/m") + " textarea").type("2{enter}", { force: true }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), + cy.get( + cesc2("#/problem34/problem1/_choiceinput1_incorrect"), + ).should("not.exist"); + cy.get(cesc2("#/problem34/problem1/_feedback1")).should( + "have.text", + `That's right, the ${animal} goes ${sound}!`, ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), + cy.get(cesc2("#/problem34/problem1/_feedback2")).should( + "not.exist", ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(x2); - expect(stateVariables["/al2/n1"].stateValues.value).eq(x2); - }); }); - cy.log("move point2"); - cy.window().then(async (win) => { - (x2 = 0), (y2 = 8); - await win.callAction1({ - actionName: "movePoint", - componentName: "/B", - args: { x: x2, y: y2 }, - }); - - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), + cy.log(`select incorrect answer for problem 1`).then(() => { + let incorrectInd = (problem1Version + 1) % 4; + let sound = soundOptions[incorrectInd]; + cy.get(cesc2("#/problem34/problem1/_choiceinput1")) + .contains(sound) + .click({ force: true }); + cy.get(cesc2("#/problem34/problem1/_choiceinput1_submit")).click(); + cy.get(cesc2("#/problem34/problem1/_choiceinput1_correct")).should( + "not.exist", ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(x2); - expect(stateVariables["/al2/n1"].stateValues.value).eq(x2); - }); - }); - - cy.log("set propIndex to 2"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y2), + cy.get( + cesc2("#/problem34/problem1/_choiceinput1_incorrect"), + ).should("be.visible"); + cy.get(cesc2("#/problem34/problem1/_feedback1")).should( + "not.exist", ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y2), + cy.get(cesc2("#/problem34/problem1/_feedback2")).should( + "have.text", + `Try again.`, ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(y2); - expect(stateVariables["/al2/n1"].stateValues.value).eq(y2); - }); }); - cy.log("set componentIndex to 1"); - cy.get(cesc("#\\/m") + " textarea").type("{end}{backspace}1{enter}", { - force: true, - }); + cy.get(cesc2("#/problem34/problem2/_title1")).should( + "have.text", + "Derivative problem", + ); cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y1), + let stateVariables = await win.returnAllStateVariables1(); + let mathinputName = + stateVariables["/problem34/problem2/_answer1"].stateValues + .inputChildren[0].componentName; + let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; + let mathinputSubmitAnchor = cesc2("#" + mathinputName + "_submit"); + let mathinputCorrectAnchor = cesc2( + "#" + mathinputName + "_correct", ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y1), + let mathinputIncorrectAnchor = cesc2( + "#" + mathinputName + "_incorrect", ); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(y1); - expect(stateVariables["/al2/n1"].stateValues.value).eq(y1); - }); - }); - - cy.log("set propIndex to 3"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); + cy.log(`enter incorrect answer for problem 2`); + cy.get(mathinputAnchor).type("2y{enter}", { force: true }); + cy.get(mathinputSubmitAnchor).should("not.exist"); + cy.get(mathinputCorrectAnchor).should("not.exist"); + cy.get(mathinputIncorrectAnchor).should("be.visible"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); - }); + cy.log(`enter correct answer for problem 2`); + cy.get(mathinputAnchor).type("{end}{backspace}x", { force: true }); + cy.get(mathinputSubmitAnchor).should("be.visible"); + cy.get(mathinputAnchor).type("{enter}", { force: true }); + cy.get(mathinputSubmitAnchor).should("not.exist"); + cy.get(mathinputCorrectAnchor).should("be.visible"); + cy.get(mathinputIncorrectAnchor).should("not.exist"); }); + }); - cy.log("set propIndex to 1"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}1{enter}", { - force: true, - }); + it("copy uri containing variant control", () => { + const doenetML = ` + Two variants from copied document + + + `; cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), + win.postMessage( + { + doenetML, + requestedVariantIndex: 1, + }, + "*", ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(x1); - expect(stateVariables["/al2/n1"].stateValues.value).eq(x1); - }); }); - cy.log("set componentIndex to 3"); - cy.get(cesc("#\\/m") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); + cy.get(cesc("#\\/_title1")).should( + "have.text", + "Two variants from copied document", + ); // to wait for page to load - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); + cy.get(cesc("#\\/thedoc")).should("contain.text", "first"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); - }); - }); + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); - cy.log("set componentIndex to 2"); - cy.get(cesc("#\\/m") + " textarea").type("{end}{backspace}2{enter}", { - force: true, + expect( + stateVariables["/thedoc"].sharedParameters.allPossibleVariants, + ).eqls(["first", "last"]); + expect(stateVariables["/thedoc"].sharedParameters.variantName).eq( + "first", + ); + expect( + stateVariables["/_document1"].sharedParameters + .allPossibleVariants, + ).eqls(["a", "b"]); + expect( + stateVariables["/_document1"].sharedParameters.variantName, + ).eq("a"); }); cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), + win.postMessage( + { + doenetML, + requestedVariantIndex: 2, + }, + "*", ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(x2); - expect(stateVariables["/al2/n1"].stateValues.value).eq(x2); - }); - }); - - cy.log("clear propIndex"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}{enter}", { - force: true, }); - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); + cy.get(cesc("#\\/thedoc")).should("contain.text", "last"); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); + + expect( + stateVariables["/thedoc"].sharedParameters.allPossibleVariants, + ).eqls(["first", "last"]); + expect(stateVariables["/thedoc"].sharedParameters.variantName).eq( + "last", + ); + expect( + stateVariables["/_document1"].sharedParameters + .allPossibleVariants, + ).eqls(["a", "b"]); + expect( + stateVariables["/_document1"].sharedParameters.variantName, + ).eq("b"); }); }); - it("copy propIndex and componentIndex, array notation, macros", () => { + it("copy uri not in a problem", () => { cy.window().then(async (win) => { win.postMessage( { doenetML: ` - a - -

m:

-

n:

- - - (1,2) - (3,4) - - - - - + - -

$(col[$m].xs[$n]{assignNames="n1"})

- -

$al{name="al2" newNamespace}

- `, }, "*", ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let x1 = 1, - y1 = 2, - x2 = 3, - y2 = 4; - - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); - }); - - cy.log("set propIndex to 1"); - - cy.get(cesc("#\\/n") + " textarea").type("1{enter}", { force: true }); - - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); - }); - - cy.log("move point 1"); - cy.window().then(async (win) => { - (x1 = 9), (y1 = -5); - await win.callAction1({ - actionName: "movePoint", - componentName: "/A", - args: { x: x1, y: y1 }, - }); - - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); - }); - }); - - cy.log("set componentIndex to 2"); - - cy.get(cesc("#\\/m") + " textarea").type("2{enter}", { force: true }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); + cy.get(cesc("#\\/problem1_title")).should("have.text", "Animal sounds"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(x2); - expect(stateVariables["/al2/n1"].stateValues.value).eq(x2); - }); - }); + let problem1Version; + let animalOptions = ["cat", "dog", "mouse", "fish"]; + let soundOptions = ["meow", "woof", "squeak", "blub"]; - cy.log("move point2"); - cy.window().then(async (win) => { - (x2 = 0), (y2 = 8); - await win.callAction1({ - actionName: "movePoint", - componentName: "/B", - args: { x: x2, y: y2 }, + cy.get(cesc2("#/problem1/_p1")) + .invoke("text") + .then((text) => { + let titleOptions = animalOptions.map( + (x) => `What does the ${x} say?`, + ); + problem1Version = titleOptions.indexOf(text); + expect(problem1Version).not.eq(-1); + cy.window().then(async (win) => { + let stateVariables = await win.returnAllStateVariables1(); + let copy1Name = stateVariables["/problem1"].replacementOf; + expect(stateVariables[copy1Name].stateValues.cid).eq( + "bafkreidqud3rixmphu3jufuke4rw7magtcrbrjgeo6ihkoyonsig7wciey", + ); + expect(stateVariables[copy1Name].stateValues.doenetId).eq( + "abcdefg", + ); + }); }); - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), + cy.log(`select correct answer for problem 1`).then(() => { + let animal = animalOptions[problem1Version]; + let sound = soundOptions[problem1Version]; + cy.get(cesc2("#/problem1/_choiceinput1")) + .contains(sound) + .click({ force: true }); + cy.get(cesc2("#/problem1/_choiceinput1_submit")).click(); + cy.get(cesc2("#/problem1/_choiceinput1_correct")).should( + "be.visible", ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(x2); - expect(stateVariables["/al2/n1"].stateValues.value).eq(x2); - }); - }); - - cy.log("set propIndex to 2"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y2), + cy.get(cesc2("#/problem1/_choiceinput1_incorrect")).should( + "not.exist", ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y2), + cy.get(cesc2("#/problem1/_feedback1")).should( + "have.text", + `That's right, the ${animal} goes ${sound}!`, ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(y2); - expect(stateVariables["/al2/n1"].stateValues.value).eq(y2); - }); - }); - - cy.log("set componentIndex to 1"); - cy.get(cesc("#\\/m") + " textarea").type("{end}{backspace}1{enter}", { - force: true, + cy.get(cesc2("#/problem1/_feedback2")).should("not.exist"); }); - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y1), - ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y1), + cy.log(`select incorrect answer for problem 1`).then(() => { + let incorrectInd = (problem1Version + 1) % 4; + let sound = soundOptions[incorrectInd]; + cy.get(cesc2("#/problem1/_choiceinput1")) + .contains(sound) + .click({ force: true }); + cy.get(cesc2("#/problem1/_choiceinput1_submit")).click(); + cy.get(cesc2("#/problem1/_choiceinput1_correct")).should( + "not.exist", ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(y1); - expect(stateVariables["/al2/n1"].stateValues.value).eq(y1); - }); - }); - - cy.log("set propIndex to 3"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); - }); - }); - - cy.log("set propIndex to 1"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}1{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), + cy.get(cesc2("#/problem1/_choiceinput1_incorrect")).should( + "be.visible", ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), + cy.get(cesc2("#/problem1/_feedback1")).should("not.exist"); + cy.get(cesc2("#/problem1/_feedback2")).should( + "have.text", + `Try again.`, ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(x1); - expect(stateVariables["/al2/n1"].stateValues.value).eq(x1); - }); - }); - - cy.log("set componentIndex to 3"); - cy.get(cesc("#\\/m") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); - }); - }); - - cy.log("set componentIndex to 2"); - cy.get(cesc("#\\/m") + " textarea").type("{end}{backspace}2{enter}", { - force: true, }); + }); + it("copyFromUri for uri not in a problem yields nothing", () => { cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), + win.postMessage( + { + doenetML: ` + + + `, + }, + "*", ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(x2); - expect(stateVariables["/al2/n1"].stateValues.value).eq(x2); - }); }); - cy.log("clear propIndex"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}{enter}", { - force: true, - }); + cy.get(cesc("#\\/problem1_title")).should("have.text", "Problem 1"); - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); + cy.get(cesc("#\\/_document1")).should( + "not.contain.text", + "Animal sounds", + ); cy.window().then(async (win) => { let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); + expect(Object.keys(stateVariables).length).eq(3); }); }); - it("copy propIndex and componentIndex, with copySource", () => { + it("copy group with link through name of external, no link", () => { cy.window().then(async (win) => { win.postMessage( { doenetML: ` a - -

m:

-

n:

- - - (1,2) - (3,4) - - - - - - + + +

Credit achieved:

+
-

- -

- + `, }, "*", ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let x1 = 1, - y1 = 2, - x2 = 3, - y2 = 4; + // to wait for page to load + cy.get(cesc("#\\/_text1")).should("have.text", "a"); cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); + let stateVariables = await win.returnAllStateVariables1(); + let mathinput1Anchor = + cesc2( + "#" + + stateVariables["/g/p/_answer1"].stateValues + .inputChildren[0].componentName, + ) + " textarea"; + let mathinput2Anchor = + cesc2( + "#" + + stateVariables["/g2/p/_answer1"].stateValues + .inputChildren[0].componentName, + ) + " textarea"; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(x2); - expect(stateVariables["/al2/n1"].stateValues.value).eq(x2); - }); - }); + cy.get(cesc2("#/g/ca")).should("have.text", "0"); + cy.get(cesc2("#/g2/ca")).should("have.text", "0"); - cy.log("move point2"); - cy.window().then(async (win) => { - (x2 = 0), (y2 = 8); - await win.callAction1({ - actionName: "movePoint", - componentName: "/B", - args: { x: x2, y: y2 }, - }); + cy.get(mathinput1Anchor).type("2x{enter}", { force: true }); - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); + cy.get(cesc2("#/g/ca")).should("have.text", "1"); + cy.get(cesc2("#/g2/ca")).should("have.text", "0"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(x2); - expect(stateVariables["/al2/n1"].stateValues.value).eq(x2); - }); - }); + cy.get(mathinput2Anchor).type("2x{enter}", { force: true }); - cy.log("set propIndex to 2"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, + cy.get(cesc2("#/g/ca")).should("have.text", "1"); + cy.get(cesc2("#/g2/ca")).should("have.text", "1"); }); + }); + it("copy group with link through name of external, no link, macros", () => { cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y2), - ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y2), + win.postMessage( + { + doenetML: ` + a + + +

Credit achieved: $(p/_answer1.creditAchieved{assignNames="ca"})

+
+ + $g{link="false" name="g2"} + `, + }, + "*", ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(y2); - expect(stateVariables["/al2/n1"].stateValues.value).eq(y2); - }); }); - cy.log("set componentIndex to 1"); - cy.get(cesc("#\\/m") + " textarea").type("{end}{backspace}1{enter}", { - force: true, - }); + // to wait for page to load + cy.get(cesc("#\\/_text1")).should("have.text", "a"); cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y1), - ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y1), - ); + let stateVariables = await win.returnAllStateVariables1(); + let mathinput1Anchor = + cesc2( + "#" + + stateVariables["/g/p/_answer1"].stateValues + .inputChildren[0].componentName, + ) + " textarea"; + let mathinput2Anchor = + cesc2( + "#" + + stateVariables["/g2/p/_answer1"].stateValues + .inputChildren[0].componentName, + ) + " textarea"; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(y1); - expect(stateVariables["/al2/n1"].stateValues.value).eq(y1); - }); - }); + cy.get(cesc2("#/g/ca")).should("have.text", "0"); + cy.get(cesc2("#/g2/ca")).should("have.text", "0"); - cy.log("set propIndex to 3"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); + cy.get(mathinput1Anchor).type("2x{enter}", { force: true }); - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - "\uff3f", - ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - "\uff3f", - ); + cy.get(cesc2("#/g/ca")).should("have.text", "1"); + cy.get(cesc2("#/g2/ca")).should("have.text", "0"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq("\uff3f"); - expect(stateVariables["/al2/n1"].stateValues.value).eq( - "\uff3f", - ); - }); - }); + cy.get(mathinput2Anchor).type("2x{enter}", { force: true }); - cy.log("set propIndex to 1"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}1{enter}", { - force: true, + cy.get(cesc2("#/g/ca")).should("have.text", "1"); + cy.get(cesc2("#/g2/ca")).should("have.text", "1"); }); + }); + it("copy group with link through name of external, no link, with copySource", () => { cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), + win.postMessage( + { + doenetML: ` + a + + +

Credit achieved:

+
+ + + `, + }, + "*", ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(x1); - expect(stateVariables["/al2/n1"].stateValues.value).eq(x1); - }); }); - cy.log("set componentIndex to 3"); - cy.get(cesc("#\\/m") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); + // to wait for page to load + cy.get(cesc("#\\/_text1")).should("have.text", "a"); cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - "\uff3f", - ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - "\uff3f", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq("\uff3f"); - expect(stateVariables["/al2/n1"].stateValues.value).eq( - "\uff3f", - ); - }); - }); + let stateVariables = await win.returnAllStateVariables1(); + let mathinput1Anchor = + cesc2( + "#" + + stateVariables["/g/p/_answer1"].stateValues + .inputChildren[0].componentName, + ) + " textarea"; + let mathinput2Anchor = + cesc2( + "#" + + stateVariables["/g2/p/_answer1"].stateValues + .inputChildren[0].componentName, + ) + " textarea"; - cy.log("set componentIndex to 2"); - cy.get(cesc("#\\/m") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); + cy.get(cesc2("#/g/ca")).should("have.text", "0"); + cy.get(cesc2("#/g2/ca")).should("have.text", "0"); - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/n2") + " .mjx-mrow").should("not.exist"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(x2); - expect(stateVariables["/al2/n1"].stateValues.value).eq(x2); - }); - }); + cy.get(mathinput1Anchor).type("2x{enter}", { force: true }); - cy.log("clear propIndex"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}{enter}", { - force: true, - }); + cy.get(cesc2("#/g/ca")).should("have.text", "1"); + cy.get(cesc2("#/g2/ca")).should("have.text", "0"); - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - "\uff3f", - ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - "\uff3f", - ); + cy.get(mathinput2Anchor).type("2x{enter}", { force: true }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq("\uff3f"); - expect(stateVariables["/al2/n1"].stateValues.value).eq( - "\uff3f", - ); - }); + cy.get(cesc2("#/g/ca")).should("have.text", "1"); + cy.get(cesc2("#/g2/ca")).should("have.text", "1"); }); }); - it("copy propIndex and componentIndex, with copySource, array notation", () => { + it("asList when copy array prop, test renderers", () => { cy.window().then(async (win) => { win.postMessage( { doenetML: ` - a - -

m:

-

n:

- - - (1,2) - (3,4) - - - - - - - -

+ + yes + no + maybe + -

+ In document: $ci.choiceTexts + $ci.choiceTexts +
$ci.choiceTexts
+ $ci.choiceTexts + $ci.choiceTexts + $ci.choiceTexts + $ci.choiceTexts + $ci.choiceTexts + $ci.choiceTexts + $ci.choiceTexts + $ci.choiceTexts + A title$ci.choiceTexts + $ci.choiceTexts + +
    +
  1. $ci.choiceTexts
  2. +
+
    +
  • $ci.choiceTexts
  • +
+

$ci.choiceTexts

+
$ci.choiceTexts
+

$ci.choiceTexts

+
Title: $ci.choiceTextsText: $ci.choiceTexts
+
$ci.choiceTexts
+ $ci.choiceTexts +

$ci.choiceTexts

+ $ci.choiceTexts `, }, @@ -17680,231 +1447,127 @@ describe("Copy Tag Tests", function () { ); }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let x1 = 1, - y1 = 2, - x2 = 3, - y2 = 4; + cy.get(cesc2("#/_document1")).should( + "contain.text", + "In document: yes, no, maybe", + ); + cy.get(cesc2("#/in_alert")).should("have.text", "yes, no, maybe"); + cy.get(cesc2("#/in_blockquote")).should("have.text", "yes, no, maybe"); + cy.get(cesc2("#/in_c")).should("have.text", "yes, no, maybe"); + cy.get(cesc2("#/in_caption")).should("have.text", "yes, no, maybe"); + cy.get(cesc2("#/in_cell")).should("have.text", "yes, no, maybe"); + cy.get(cesc2("#/in_choice")).should("have.text", "yes, no, maybe"); + cy.get(cesc2("#/in_span")).should("have.text", "yes, no, maybe"); + cy.get(cesc2("#/in_em")).should("have.text", "yes, no, maybe"); + cy.get(cesc2("#/in_feedback")).should("have.text", "yes, no, maybe"); + cy.get(cesc2("#/in_footnote")).click(); + cy.get(cesc2("#/in_footnote")).should("contain.text", "yes, no, maybe"); + cy.get(cesc2("#/in_hint_w_title")).click(); + cy.get(cesc2("#/in_hint_w_title")).should( + "contain.text", + "yes, no, maybe", + ); + cy.get(cesc2("#/in_hint_wo_title")).click(); + cy.get(cesc2("#/in_hint_wo_title")).should( + "contain.text", + "yes, no, maybe", + ); + cy.get(cesc2("#/in_label")).should("have.text", "yes, no, maybe"); + cy.get(cesc2("#/in_li")).should("have.text", "yes, no, maybe"); + cy.get(cesc2("#/in_li2")).should("have.text", "yes, no, maybe"); + cy.get(cesc2("#/in_p")).should("have.text", "yes, no, maybe"); + cy.get(cesc2("#/in_pre")).should("have.text", "yes, no, maybe"); + cy.get(cesc2("#/in_q")).should("have.text", "“yes, no, maybe”"); + cy.get(cesc2("#/in_section_w_title")).should( + "contain.text", + "Title: yes, no, maybe", + ); + cy.get(cesc2("#/in_section_w_title")).should( + "contain.text", + "Text: yes, no, maybe", + ); + cy.get(cesc2("#/in_section_wo_title")).should( + "contain.text", + "yes, no, maybe", + ); + cy.get(cesc2("#/in_solution")).click(); + cy.get(cesc2("#/in_solution")).should("contain.text", "yes, no, maybe"); + cy.get(cesc2("#/in_sq")).should("have.text", "‘yes, no, maybe’"); + cy.get(cesc2("#/in_text")).should("have.text", "yes, no, maybe"); cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), + let stateVariables = await win.returnAllStateVariables1(); + expect(stateVariables["/in_alert"].stateValues.text).eq( + "yes, no, maybe", ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), + expect(stateVariables["/in_c"].stateValues.text).eq( + "yes, no, maybe", ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(x2); - expect(stateVariables["/al2/n1"].stateValues.value).eq(x2); - }); - }); - - cy.log("move point2"); - cy.window().then(async (win) => { - (x2 = 0), (y2 = 8); - await win.callAction1({ - actionName: "movePoint", - componentName: "/B", - args: { x: x2, y: y2 }, - }); - - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), + expect(stateVariables["/in_caption"].stateValues.text).eq( + "yes, no, maybe", ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), + expect(stateVariables["/in_cell"].stateValues.text).eq( + "yes, no, maybe", ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(x2); - expect(stateVariables["/al2/n1"].stateValues.value).eq(x2); - }); - }); - - cy.log("set propIndex to 2"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y2), + expect(stateVariables["/in_choice"].stateValues.text).eq( + "yes, no, maybe", ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y2), + expect(stateVariables["/in_em"].stateValues.text).eq( + "yes, no, maybe", ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(y2); - expect(stateVariables["/al2/n1"].stateValues.value).eq(y2); - }); - }); - - cy.log("set componentIndex to 1"); - cy.get(cesc("#\\/m") + " textarea").type("{end}{backspace}1{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y1), + expect(stateVariables["/in_footnote"].stateValues.text).eq( + "yes, no, maybe", ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y1), + expect(stateVariables["/in_label"].stateValues.text).eq( + "yes, no, maybe", ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(y1); - expect(stateVariables["/al2/n1"].stateValues.value).eq(y1); - }); - }); - - cy.log("set propIndex to 3"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - "\uff3f", + expect(stateVariables["/in_p"].stateValues.text).eq( + "yes, no, maybe", ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - "\uff3f", + expect(stateVariables["/in_text"].stateValues.text).eq( + "yes, no, maybe", + ); + expect(stateVariables["/sec_title"].stateValues.text).eq( + "Title: yes, no, maybe", ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq("\uff3f"); - expect(stateVariables["/al2/n1"].stateValues.value).eq( - "\uff3f", - ); - }); - }); - - cy.log("set propIndex to 1"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}1{enter}", { - force: true, }); + }); + it("copy number from external content multiple ways, change attributes", () => { cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); + win.postMessage( + { + doenetML: ` - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(x1); - expect(stateVariables["/al2/n1"].stateValues.value).eq(x1); - }); - }); +

- cy.log("set componentIndex to 3"); - cy.get(cesc("#\\/m") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); +

- cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - "\uff3f", - ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - "\uff3f", - ); +

- cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq("\uff3f"); - expect(stateVariables["/al2/n1"].stateValues.value).eq( - "\uff3f", - ); - }); - }); +

- cy.log("set componentIndex to 2"); - cy.get(cesc("#\\/m") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); +

- cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/n2") + " .mjx-mrow").should("not.exist"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(x2); - expect(stateVariables["/al2/n1"].stateValues.value).eq(x2); - }); - }); +

- cy.log("clear propIndex"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}{enter}", { - force: true, - }); +

- cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - "\uff3f", - ); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - "\uff3f", - ); +

- cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq("\uff3f"); - expect(stateVariables["/al2/n1"].stateValues.value).eq( - "\uff3f", - ); - }); + `, + }, + "*", + ); }); + + cy.get(cesc("#\\/_p1")).should("have.text", "8.85"); + cy.get(cesc("#\\/n2")).should("have.text", "8.853729375"); + cy.get(cesc("#\\/_number1")).should("have.text", "8.85"); + cy.get(cesc("#\\/n4")).should("have.text", "8.853729375"); + cy.get(cesc("#\\/_p5")).should("have.text", "8.85"); + cy.get(cesc("#\\/n6")).should("have.text", "8.853729375"); + cy.get(cesc("#\\/_number3")).should("have.text", "8.85"); + cy.get(cesc("#\\/n8")).should("have.text", "8.853729375"); }); }); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/copy2.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/copy2.cy.js deleted file mode 100644 index 1744e1763..000000000 --- a/packages/test-cypress/cypress/e2e/tagSpecific/copy2.cy.js +++ /dev/null @@ -1,7718 +0,0 @@ -import { cesc, cesc2 } from "@doenet/utils"; - -function nInDOM(n) { - if (n < 0) { - return `−${Math.abs(n)}`; - } else { - return String(n); - } -} - -describe("Copy Tag Tests 2", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("source attributes to ignore", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

The text: secret

- -

Text stays hidden by default:

- $p1{name="p2"} -

Check attributes: $p2.hidden $p2.fixed $p2.isResponse $(p2/hidden.hidden) $(p2/hidden.fixed) $(p2/hidden.isResponse)

- -

Now all is revealed:

- -

Check attributes: $p5.hidden $p5.fixed $p5.isResponse $(p5/hidden.hidden) $(p5/hidden.fixed) $(p5/hidden.isResponse)

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/p1")).should("have.text", "The text: "); - - cy.get(cesc("#\\/p2")).should("have.text", "The text: "); - cy.get(cesc("#\\/p4")).should( - "have.text", - "Check attributes: false true false true true false", - ); - - cy.get(cesc("#\\/p5")).should("have.text", "The text: secret"); - cy.get(cesc("#\\/p7")).should( - "have.text", - "Check attributes: false false true false false true", - ); - }); - - it("copySource", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (1,2) - - - - (3,4) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let P1 = [1, 2]; - let P2 = [3, 4]; - - cy.get(cesc2("#/P1x")).contains(`${P1[0]}`); - cy.get(cesc2("#/P2x")).contains(`${P2[0]}`); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g5PName = stateVariables["/g5"].activeChildren[0].componentName; - let g7PName = stateVariables["/g7"].activeChildren[0].componentName; - let g13PName = - stateVariables["/g13"].activeChildren[0].componentName; - let g15PName = - stateVariables["/g15"].activeChildren[0].componentName; - let g21PName = - stateVariables["/g21"].activeChildren[0].componentName; - let g23PName = - stateVariables["/g23"].activeChildren[0].componentName; - - expect(stateVariables["/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g2/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g4/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g5PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g6/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g7PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g8/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g9/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g10/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g11/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g12/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g13PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g14/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g15PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g16/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g17/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g18/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g19/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g20/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g21PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g22/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g23PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g24/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g25/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g26/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g27/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g28/Pa"].stateValues.xs).eqls(P2); - - cy.log(`move P1 to (4,5)`); - cy.window().then(async (win) => { - P1 = [4, 5]; - - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: P1[0], y: P1[1] }, - }); - - cy.get(cesc2("#/P1x")).contains(`${P1[0]}`); - cy.get(cesc2("#/P2x")).contains(`${P2[0]}`); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g2/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g4/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g5PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g6/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g7PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g8/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g9/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g10/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g11/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g12/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g13PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g14/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g15PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g16/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g17/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g18/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g19/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g20/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g21PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g22/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g23PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g24/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g25/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g26/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g27/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g28/Pa"].stateValues.xs).eqls(P2); - }); - - cy.log(`move P2 to (7,0)`); - cy.window().then(async (win) => { - P2 = [7, 0]; - await win.callAction1({ - actionName: "movePoint", - componentName: "/g2/P", - args: { x: P2[0], y: P2[1] }, - }); - - cy.get(cesc2("#/P2x")).contains(`${P2[0]}`); - cy.get(cesc2("#/P1x")).contains(`${P1[0]}`); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g2/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g4/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g5PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g6/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g7PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g8/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g9/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g10/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g11/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g12/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g13PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g14/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g15PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g16/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g17/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g18/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g19/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g20/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g21PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g22/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g23PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g24/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g25/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g26/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g27/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g28/Pa"].stateValues.xs).eqls(P2); - }); - - cy.log(`move P1 via Pa to (2,9)`); - cy.window().then(async (win) => { - P1 = [2, 0]; - - await win.callAction1({ - actionName: "movePoint", - componentName: "/Pa", - args: { x: P1[0], y: P1[1] }, - }); - - cy.get(cesc2("#/P1x")).contains(`${P1[0]}`); - cy.get(cesc2("#/P2x")).contains(`${P2[0]}`); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g2/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g4/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g5PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g6/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g7PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g8/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g9/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g10/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g11/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g12/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g13PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g14/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g15PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g16/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g17/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g18/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g19/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g20/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g21PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g22/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g23PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g24/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g25/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g26/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g27/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g28/Pa"].stateValues.xs).eqls(P2); - }); - - cy.log(`move P2 via graph 4's Pa to (8, 6)`); - cy.window().then(async (win) => { - P2 = [8, 6]; - await win.callAction1({ - actionName: "movePoint", - componentName: "/g4/Pa", - args: { x: P2[0], y: P2[1] }, - }); - - cy.get(cesc2("#/P2x")).contains(`${P2[0]}`); - cy.get(cesc2("#/P1x")).contains(`${P1[0]}`); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g2/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g4/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g5PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g6/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g7PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g8/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g9/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g10/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g11/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g12/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g13PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g14/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g15PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g16/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g17/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g18/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g19/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g20/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g21PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g22/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g23PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g24/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g25/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g26/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g27/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g28/Pa"].stateValues.xs).eqls(P2); - }); - }); - }); - - it("copySource and copies with newNamespace", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (1,2) - - $P.x{name="P1x"} - - (3,4) - - $(g2/P.x{name="P2x"}) - - - - - - - - - - - - $g1{name="g9" newNamespace} - $g2{name="g10" newNamespace} - $g3{name="g11" newNamespace} - $g4{name="g12" newNamespace} - - - - - - - - - - - $g5{name="g21" newNamespace} - $g6{name="g22" newNamespace} - $g7{name="g23" newNamespace} - $g8{name="g24" newNamespace} - $g9{name="g25" newNamespace} - $g10{name="g26" newNamespace} - $g11{name="g27" newNamespace} - $g12{name="g28" newNamespace} - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let P1 = [1, 2]; - let P2 = [3, 4]; - - cy.get(cesc2("#/P1x")).contains(`${P1[0]}`); - cy.get(cesc2("#/P2x")).contains(`${P2[0]}`); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g5PName = stateVariables["/g5"].activeChildren[0].componentName; - let g7PName = stateVariables["/g7"].activeChildren[0].componentName; - let g13PName = - stateVariables["/g13"].activeChildren[0].componentName; - let g15PName = - stateVariables["/g15"].activeChildren[0].componentName; - let g21PName = - stateVariables["/g21"].activeChildren[0].componentName; - let g23PName = - stateVariables["/g23"].activeChildren[0].componentName; - - expect(stateVariables["/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g2/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g4/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g5PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g6/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g7PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g8/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g9/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g10/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g11/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g12/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g13PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g14/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g15PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g16/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g17/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g18/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g19/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g20/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g21PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g22/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g23PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g24/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g25/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g26/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g27/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g28/Pa"].stateValues.xs).eqls(P2); - - cy.log(`move P1 to (4,5)`); - cy.window().then(async (win) => { - P1 = [4, 5]; - - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: P1[0], y: P1[1] }, - }); - - cy.get(cesc2("#/P1x")).contains(`${P1[0]}`); - cy.get(cesc2("#/P2x")).contains(`${P2[0]}`); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g2/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g4/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g5PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g6/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g7PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g8/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g9/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g10/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g11/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g12/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g13PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g14/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g15PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g16/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g17/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g18/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g19/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g20/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g21PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g22/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g23PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g24/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g25/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g26/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g27/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g28/Pa"].stateValues.xs).eqls(P2); - }); - - cy.log(`move P2 to (7,0)`); - cy.window().then(async (win) => { - P2 = [7, 0]; - await win.callAction1({ - actionName: "movePoint", - componentName: "/g2/P", - args: { x: P2[0], y: P2[1] }, - }); - - cy.get(cesc2("#/P2x")).contains(`${P2[0]}`); - cy.get(cesc2("#/P1x")).contains(`${P1[0]}`); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g2/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g4/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g5PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g6/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g7PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g8/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g9/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g10/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g11/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g12/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g13PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g14/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g15PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g16/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g17/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g18/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g19/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g20/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g21PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g22/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g23PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g24/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g25/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g26/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g27/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g28/Pa"].stateValues.xs).eqls(P2); - }); - - cy.log(`move P1 via Pa to (2,9)`); - cy.window().then(async (win) => { - P1 = [2, 0]; - - await win.callAction1({ - actionName: "movePoint", - componentName: "/Pa", - args: { x: P1[0], y: P1[1] }, - }); - - cy.get(cesc2("#/P1x")).contains(`${P1[0]}`); - cy.get(cesc2("#/P2x")).contains(`${P2[0]}`); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g2/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g4/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g5PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g6/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g7PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g8/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g9/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g10/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g11/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g12/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g13PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g14/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g15PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g16/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g17/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g18/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g19/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g20/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g21PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g22/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g23PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g24/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g25/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g26/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g27/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g28/Pa"].stateValues.xs).eqls(P2); - }); - - cy.log(`move P2 via graph 4's Pa to (8, 6)`); - cy.window().then(async (win) => { - P2 = [8, 6]; - await win.callAction1({ - actionName: "movePoint", - componentName: "/g4/Pa", - args: { x: P2[0], y: P2[1] }, - }); - - cy.get(cesc2("#/P2x")).contains(`${P2[0]}`); - cy.get(cesc2("#/P1x")).contains(`${P1[0]}`); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g2/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g4/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g5PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g6/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g7PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g8/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g9/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g10/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g11/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g12/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g13PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g14/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g15PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g16/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g17/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g18/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g19/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g20/Pa"].stateValues.xs).eqls(P2); - - expect(stateVariables[g21PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g22/P"].stateValues.xs).eqls(P2); - expect(stateVariables[g23PName].stateValues.xs).eqls(P1); - expect(stateVariables["/g24/Pa"].stateValues.xs).eqls(P2); - expect(stateVariables["/g25/P"].stateValues.xs).eqls(P1); - expect(stateVariables["/g26/P"].stateValues.xs).eqls(P2); - expect(stateVariables["/g27/Pa"].stateValues.xs).eqls(P1); - expect(stateVariables["/g28/Pa"].stateValues.xs).eqls(P2); - }); - }); - }); - - it("copy with newNamespace and references to parent", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - x - - - y -

Credit achieved: $p1.creditAchieved{assignNames="ca"}

-

Value of mathinput: $mi.value{assignNames="m"}

-

Other answer credit achieved: $(p2/_answer1.creditAchieved{assignNames="cao"})

-
- - - z -

Credit achieved: $(../p2.creditAchieved{assignNames="ca"})

-

Value of mathinput: $(../mi.value{assignNames="m"})

-

Other answer credit achieved: $(../_answer2.creditAchieved{assignNames="cao"})

-
- - $p1{name="p3" newNamespace} - - $p2{name="p4" newNamespace} - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/ca")).contains("0"); - cy.get(cesc2("#/p2/cao")).contains("0"); - cy.get(cesc2("#/p3/ca")).contains("0"); - cy.get(cesc2("#/p4/cao")).contains("0"); - - cy.get(cesc2("#/cao")).contains("0"); - cy.get(cesc2("#/p2/ca")).contains("0"); - cy.get(cesc2("#/p3/cao")).contains("0"); - cy.get(cesc2("#/p4/ca")).contains("0"); - - cy.get(cesc2("#/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p2/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p3/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p4/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let mathinputoutsideName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinputoutsideAnchor = - cesc2("#" + mathinputoutsideName) + " textarea"; - let mathinputoutsideSubmitAnchor = cesc2( - "#" + mathinputoutsideName + "_submit", - ); - let mathinputoutsideCorrectAnchor = cesc2( - "#" + mathinputoutsideName + "_correct", - ); - let mathinputoutsideIncorrectAnchor = cesc2( - "#" + mathinputoutsideName + "_incorrect", - ); - let mathinputoutsideFieldAnchor = - cesc2("#" + mathinputoutsideName) + " .mq-editable-field"; - - let mathinputp1Name = - stateVariables["/_answer2"].stateValues.inputChildren[0] - .componentName; - let mathinputp1Anchor = cesc2("#" + mathinputp1Name) + " textarea"; - let mathinputp1SubmitAnchor = cesc2( - "#" + mathinputp1Name + "_submit", - ); - let mathinputp1CorrectAnchor = cesc2( - "#" + mathinputp1Name + "_correct", - ); - let mathinputp1IncorrectAnchor = cesc2( - "#" + mathinputp1Name + "_incorrect", - ); - let mathinputp1FieldAnchor = - cesc2("#" + mathinputp1Name) + " .mq-editable-field"; - - let mathinputp2Name = - stateVariables["/p2/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinputp2Anchor = cesc2("#" + mathinputp2Name) + " textarea"; - let mathinputp2SubmitAnchor = cesc2( - "#" + mathinputp2Name + "_submit", - ); - let mathinputp2CorrectAnchor = cesc2( - "#" + mathinputp2Name + "_correct", - ); - let mathinputp2IncorrectAnchor = cesc2( - "#" + mathinputp2Name + "_incorrect", - ); - let mathinputp2FieldAnchor = - cesc2("#" + mathinputp2Name) + " .mq-editable-field"; - - let mathinputp3Name = - stateVariables["/p3/_answer2"].stateValues.inputChildren[0] - .componentName; - let mathinputp3Anchor = cesc2("#" + mathinputp3Name) + " textarea"; - let mathinputp3SubmitAnchor = cesc2( - "#" + mathinputp3Name + "_submit", - ); - let mathinputp3CorrectAnchor = cesc2( - "#" + mathinputp3Name + "_correct", - ); - let mathinputp3IncorrectAnchor = cesc2( - "#" + mathinputp3Name + "_incorrect", - ); - let mathinputp3FieldAnchor = - cesc2("#" + mathinputp3Name) + " .mq-editable-field"; - - let mathinputp4Name = - stateVariables["/p4/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinputp4Anchor = cesc2("#" + mathinputp4Name) + " textarea"; - let mathinputp4SubmitAnchor = cesc2( - "#" + mathinputp4Name + "_submit", - ); - let mathinputp4CorrectAnchor = cesc2( - "#" + mathinputp4Name + "_correct", - ); - let mathinputp4IncorrectAnchor = cesc2( - "#" + mathinputp4Name + "_incorrect", - ); - let mathinputp4FieldAnchor = - cesc2("#" + mathinputp4Name) + " .mq-editable-field"; - - expect(stateVariables["/ca"].stateValues.value).eq(0); - expect(stateVariables["/p2/cao"].stateValues.value).eq(0); - expect(stateVariables["/p3/ca"].stateValues.value).eq(0); - expect(stateVariables["/p4/cao"].stateValues.value).eq(0); - - expect(stateVariables["/cao"].stateValues.value).eq(0); - expect(stateVariables["/p2/ca"].stateValues.value).eq(0); - expect(stateVariables["/p3/cao"].stateValues.value).eq(0); - expect(stateVariables["/p4/ca"].stateValues.value).eq(0); - - expect(stateVariables["/m"].stateValues.value).eq("p"); - expect(stateVariables["/p2/m"].stateValues.value).eq("p"); - expect(stateVariables["/p3/m"].stateValues.value).eq("p"); - expect(stateVariables["/p4/m"].stateValues.value).eq("p"); - - cy.log("answer outside answer"); - - cy.get(mathinputoutsideAnchor).type("x{enter}", { force: true }); - cy.get(mathinputoutsideCorrectAnchor).should("be.visible"); - cy.get(mathinputp1SubmitAnchor).should("be.visible"); - cy.get(mathinputp2SubmitAnchor).should("be.visible"); - cy.get(mathinputp3SubmitAnchor).should("be.visible"); - cy.get(mathinputp4SubmitAnchor).should("be.visible"); - - cy.log("correctly answer first problem"); - cy.get(mathinputp1Anchor).type("y{enter}", { force: true }); - cy.get(mathinputp1CorrectAnchor).should("be.visible"); - cy.get(mathinputp2SubmitAnchor).should("be.visible"); - cy.get(mathinputp3CorrectAnchor).should("be.visible"); - cy.get(mathinputp4SubmitAnchor).should("be.visible"); - - cy.get(mathinputp1FieldAnchor) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "y", - ); - }); - cy.get(mathinputp2FieldAnchor).should("have.text", ""); - cy.get(mathinputp3FieldAnchor).should("have.text", "y"); - cy.get(mathinputp4FieldAnchor).should("have.text", ""); - - cy.get(cesc2("#/ca")).contains("1"); - cy.get(cesc2("#/p2/cao")).contains("1"); - cy.get(cesc2("#/p3/ca")).contains("1"); - cy.get(cesc2("#/p4/cao")).contains("1"); - - cy.get(cesc2("#/cao")).contains("0"); - cy.get(cesc2("#/p2/ca")).contains("0"); - cy.get(cesc2("#/p3/cao")).contains("0"); - cy.get(cesc2("#/p4/ca")).contains("0"); - - cy.get(cesc2("#/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p2/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p3/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p4/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ca"].stateValues.value).eq(1); - expect(stateVariables["/p2/cao"].stateValues.value).eq(1); - expect(stateVariables["/p3/ca"].stateValues.value).eq(1); - expect(stateVariables["/p4/cao"].stateValues.value).eq(1); - - expect(stateVariables["/cao"].stateValues.value).eq(0); - expect(stateVariables["/p2/ca"].stateValues.value).eq(0); - expect(stateVariables["/p3/cao"].stateValues.value).eq(0); - expect(stateVariables["/p4/ca"].stateValues.value).eq(0); - - expect(stateVariables["/m"].stateValues.value).eq("p"); - expect(stateVariables["/p2/m"].stateValues.value).eq("p"); - expect(stateVariables["/p3/m"].stateValues.value).eq("p"); - expect(stateVariables["/p4/m"].stateValues.value).eq("p"); - }); - - cy.log("correctly answer second problem"); - cy.get(mathinputp2Anchor).type("z{enter}", { force: true }); - cy.get(mathinputp2CorrectAnchor).should("be.visible"); - cy.get(mathinputp1CorrectAnchor).should("be.visible"); - cy.get(mathinputp3CorrectAnchor).should("be.visible"); - cy.get(mathinputp4CorrectAnchor).should("be.visible"); - - cy.get(mathinputp2FieldAnchor) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "z", - ); - }); - cy.get(mathinputp1FieldAnchor).should("have.text", "y"); - cy.get(mathinputp3FieldAnchor).should("have.text", "y"); - cy.get(mathinputp4FieldAnchor).should("have.text", "z"); - - cy.get(cesc2("#/ca")).contains("1"); - cy.get(cesc2("#/p2/cao")).contains("1"); - cy.get(cesc2("#/p3/ca")).contains("1"); - cy.get(cesc2("#/p4/cao")).contains("1"); - - cy.get(cesc2("#/cao")).contains("1"); - cy.get(cesc2("#/p2/ca")).contains("1"); - cy.get(cesc2("#/p3/cao")).contains("1"); - cy.get(cesc2("#/p4/ca")).contains("1"); - - cy.get(cesc2("#/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p2/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p3/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p4/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ca"].stateValues.value).eq(1); - expect(stateVariables["/p2/cao"].stateValues.value).eq(1); - expect(stateVariables["/p3/ca"].stateValues.value).eq(1); - expect(stateVariables["/p4/cao"].stateValues.value).eq(1); - - expect(stateVariables["/cao"].stateValues.value).eq(1); - expect(stateVariables["/p2/ca"].stateValues.value).eq(1); - expect(stateVariables["/p3/cao"].stateValues.value).eq(1); - expect(stateVariables["/p4/ca"].stateValues.value).eq(1); - - expect(stateVariables["/m"].stateValues.value).eq("p"); - expect(stateVariables["/p2/m"].stateValues.value).eq("p"); - expect(stateVariables["/p3/m"].stateValues.value).eq("p"); - expect(stateVariables["/p4/m"].stateValues.value).eq("p"); - }); - - cy.log("incorrectly answer third problem"); - cy.get(mathinputp3Anchor).type("{end}{backspace}a{enter}", { - force: true, - }); - cy.get(mathinputp3IncorrectAnchor).should("be.visible"); - cy.get(mathinputp1IncorrectAnchor).should("be.visible"); - cy.get(mathinputp2CorrectAnchor).should("be.visible"); - cy.get(mathinputp4CorrectAnchor).should("be.visible"); - - cy.get(mathinputp3FieldAnchor) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "a", - ); - }); - cy.get(mathinputp1FieldAnchor).should("have.text", "a"); - cy.get(mathinputp2FieldAnchor).should("have.text", "z"); - cy.get(mathinputp4FieldAnchor).should("have.text", "z"); - - cy.get(cesc2("#/ca")).contains("0"); - cy.get(cesc2("#/p2/cao")).contains("0"); - cy.get(cesc2("#/p3/ca")).contains("0"); - cy.get(cesc2("#/p4/cao")).contains("0"); - - cy.get(cesc2("#/cao")).contains("1"); - cy.get(cesc2("#/p2/ca")).contains("1"); - cy.get(cesc2("#/p3/cao")).contains("1"); - cy.get(cesc2("#/p4/ca")).contains("1"); - - cy.get(cesc2("#/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p2/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p3/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p4/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ca"].stateValues.value).eq(0); - expect(stateVariables["/p2/cao"].stateValues.value).eq(0); - expect(stateVariables["/p3/ca"].stateValues.value).eq(0); - expect(stateVariables["/p4/cao"].stateValues.value).eq(0); - - expect(stateVariables["/cao"].stateValues.value).eq(1); - expect(stateVariables["/p2/ca"].stateValues.value).eq(1); - expect(stateVariables["/p3/cao"].stateValues.value).eq(1); - expect(stateVariables["/p4/ca"].stateValues.value).eq(1); - - expect(stateVariables["/m"].stateValues.value).eq("p"); - expect(stateVariables["/p2/m"].stateValues.value).eq("p"); - expect(stateVariables["/p3/m"].stateValues.value).eq("p"); - expect(stateVariables["/p4/m"].stateValues.value).eq("p"); - }); - - cy.log("incorrectly answer fourth problem"); - cy.get(mathinputp4Anchor).type("{end}{backspace}b{enter}", { - force: true, - }); - cy.get(mathinputp4IncorrectAnchor).should("be.visible"); - cy.get(mathinputp1IncorrectAnchor).should("be.visible"); - cy.get(mathinputp2IncorrectAnchor).should("be.visible"); - cy.get(mathinputp3IncorrectAnchor).should("be.visible"); - - cy.get(mathinputp4FieldAnchor) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "b", - ); - }); - cy.get(mathinputp1FieldAnchor).should("have.text", "a"); - cy.get(mathinputp2FieldAnchor).should("have.text", "b"); - cy.get(mathinputp3FieldAnchor).should("have.text", "a"); - - cy.get(cesc2("#/ca")).contains("0"); - cy.get(cesc2("#/p2/cao")).contains("0"); - cy.get(cesc2("#/p3/ca")).contains("0"); - cy.get(cesc2("#/p4/cao")).contains("0"); - - cy.get(cesc2("#/cao")).contains("0"); - cy.get(cesc2("#/p2/ca")).contains("0"); - cy.get(cesc2("#/p3/cao")).contains("0"); - cy.get(cesc2("#/p4/ca")).contains("0"); - - cy.get(cesc2("#/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p2/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p3/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p4/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ca"].stateValues.value).eq(0); - expect(stateVariables["/p2/cao"].stateValues.value).eq(0); - expect(stateVariables["/p3/ca"].stateValues.value).eq(0); - expect(stateVariables["/p4/cao"].stateValues.value).eq(0); - - expect(stateVariables["/cao"].stateValues.value).eq(0); - expect(stateVariables["/p2/ca"].stateValues.value).eq(0); - expect(stateVariables["/p3/cao"].stateValues.value).eq(0); - expect(stateVariables["/p4/ca"].stateValues.value).eq(0); - - expect(stateVariables["/m"].stateValues.value).eq("p"); - expect(stateVariables["/p2/m"].stateValues.value).eq("p"); - expect(stateVariables["/p3/m"].stateValues.value).eq("p"); - expect(stateVariables["/p4/m"].stateValues.value).eq("p"); - }); - - cy.log("change mathinput"); - cy.get(cesc2("#/mi") + " textarea").type( - "{end}{backspace}q{enter}", - { - force: true, - }, - ); - cy.get(cesc2("#/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "q"); - cy.get(cesc2("#/p2/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "q"); - cy.get(cesc2("#/p3/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "q"); - cy.get(cesc2("#/p4/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "q"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/m"].stateValues.value).eq("q"); - expect(stateVariables["/p2/m"].stateValues.value).eq("q"); - expect(stateVariables["/p3/m"].stateValues.value).eq("q"); - expect(stateVariables["/p4/m"].stateValues.value).eq("q"); - }); - }); - }); - - it("copySource with newNamespace and references to parent", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - x - - - y -

Credit achieved:

-

Value of mathinput:

-

Other answer credit achieved:

-
- - - z -

Credit achieved:

-

Value of mathinput:

-

Other answer credit achieved:

-
- - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/ca")).contains("0"); - cy.get(cesc2("#/p2/cao")).contains("0"); - cy.get(cesc2("#/p3/ca")).contains("0"); - cy.get(cesc2("#/p4/cao")).contains("0"); - - cy.get(cesc2("#/cao")).contains("0"); - cy.get(cesc2("#/p2/ca")).contains("0"); - cy.get(cesc2("#/p3/cao")).contains("0"); - cy.get(cesc2("#/p4/ca")).contains("0"); - - cy.get(cesc2("#/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p2/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p3/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p4/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let mathinputoutsideName = - stateVariables["/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinputoutsideAnchor = - cesc2("#" + mathinputoutsideName) + " textarea"; - let mathinputoutsideSubmitAnchor = cesc2( - "#" + mathinputoutsideName + "_submit", - ); - let mathinputoutsideCorrectAnchor = cesc2( - "#" + mathinputoutsideName + "_correct", - ); - let mathinputoutsideIncorrectAnchor = cesc2( - "#" + mathinputoutsideName + "_incorrect", - ); - let mathinputoutsideFieldAnchor = - cesc2("#" + mathinputoutsideName) + " .mq-editable-field"; - - let mathinputp1Name = - stateVariables["/_answer2"].stateValues.inputChildren[0] - .componentName; - let mathinputp1Anchor = cesc2("#" + mathinputp1Name) + " textarea"; - let mathinputp1SubmitAnchor = cesc2( - "#" + mathinputp1Name + "_submit", - ); - let mathinputp1CorrectAnchor = cesc2( - "#" + mathinputp1Name + "_correct", - ); - let mathinputp1IncorrectAnchor = cesc2( - "#" + mathinputp1Name + "_incorrect", - ); - let mathinputp1FieldAnchor = - cesc2("#" + mathinputp1Name) + " .mq-editable-field"; - - let mathinputp2Name = - stateVariables["/p2/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinputp2Anchor = cesc2("#" + mathinputp2Name) + " textarea"; - let mathinputp2SubmitAnchor = cesc2( - "#" + mathinputp2Name + "_submit", - ); - let mathinputp2CorrectAnchor = cesc2( - "#" + mathinputp2Name + "_correct", - ); - let mathinputp2IncorrectAnchor = cesc2( - "#" + mathinputp2Name + "_incorrect", - ); - let mathinputp2FieldAnchor = - cesc2("#" + mathinputp2Name) + " .mq-editable-field"; - - let mathinputp3Name = - stateVariables["/p3/_answer2"].stateValues.inputChildren[0] - .componentName; - let mathinputp3Anchor = cesc2("#" + mathinputp3Name) + " textarea"; - let mathinputp3SubmitAnchor = cesc2( - "#" + mathinputp3Name + "_submit", - ); - let mathinputp3CorrectAnchor = cesc2( - "#" + mathinputp3Name + "_correct", - ); - let mathinputp3IncorrectAnchor = cesc2( - "#" + mathinputp3Name + "_incorrect", - ); - let mathinputp3FieldAnchor = - cesc2("#" + mathinputp3Name) + " .mq-editable-field"; - - let mathinputp4Name = - stateVariables["/p4/_answer1"].stateValues.inputChildren[0] - .componentName; - let mathinputp4Anchor = cesc2("#" + mathinputp4Name) + " textarea"; - let mathinputp4SubmitAnchor = cesc2( - "#" + mathinputp4Name + "_submit", - ); - let mathinputp4CorrectAnchor = cesc2( - "#" + mathinputp4Name + "_correct", - ); - let mathinputp4IncorrectAnchor = cesc2( - "#" + mathinputp4Name + "_incorrect", - ); - let mathinputp4FieldAnchor = - cesc2("#" + mathinputp4Name) + " .mq-editable-field"; - - expect(stateVariables["/ca"].stateValues.value).eq(0); - expect(stateVariables["/p2/cao"].stateValues.value).eq(0); - expect(stateVariables["/p3/ca"].stateValues.value).eq(0); - expect(stateVariables["/p4/cao"].stateValues.value).eq(0); - - expect(stateVariables["/cao"].stateValues.value).eq(0); - expect(stateVariables["/p2/ca"].stateValues.value).eq(0); - expect(stateVariables["/p3/cao"].stateValues.value).eq(0); - expect(stateVariables["/p4/ca"].stateValues.value).eq(0); - - expect(stateVariables["/m"].stateValues.value).eq("p"); - expect(stateVariables["/p2/m"].stateValues.value).eq("p"); - expect(stateVariables["/p3/m"].stateValues.value).eq("p"); - expect(stateVariables["/p4/m"].stateValues.value).eq("p"); - - cy.log("answer outside answer"); - - cy.get(mathinputoutsideAnchor).type("x{enter}", { force: true }); - cy.get(mathinputoutsideCorrectAnchor).should("be.visible"); - cy.get(mathinputp1SubmitAnchor).should("be.visible"); - cy.get(mathinputp2SubmitAnchor).should("be.visible"); - cy.get(mathinputp3SubmitAnchor).should("be.visible"); - cy.get(mathinputp4SubmitAnchor).should("be.visible"); - - cy.log("correctly answer first problem"); - cy.get(mathinputp1Anchor).type("y{enter}", { force: true }); - cy.get(mathinputp1CorrectAnchor).should("be.visible"); - cy.get(mathinputp2SubmitAnchor).should("be.visible"); - cy.get(mathinputp3CorrectAnchor).should("be.visible"); - cy.get(mathinputp4SubmitAnchor).should("be.visible"); - - cy.get(mathinputp1FieldAnchor) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "y", - ); - }); - cy.get(mathinputp2FieldAnchor).should("have.text", ""); - cy.get(mathinputp3FieldAnchor).should("have.text", "y"); - cy.get(mathinputp4FieldAnchor).should("have.text", ""); - - cy.get(cesc2("#/ca")).contains("1"); - cy.get(cesc2("#/p2/cao")).contains("1"); - cy.get(cesc2("#/p3/ca")).contains("1"); - cy.get(cesc2("#/p4/cao")).contains("1"); - - cy.get(cesc2("#/cao")).contains("0"); - cy.get(cesc2("#/p2/ca")).contains("0"); - cy.get(cesc2("#/p3/cao")).contains("0"); - cy.get(cesc2("#/p4/ca")).contains("0"); - - cy.get(cesc2("#/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p2/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p3/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p4/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ca"].stateValues.value).eq(1); - expect(stateVariables["/p2/cao"].stateValues.value).eq(1); - expect(stateVariables["/p3/ca"].stateValues.value).eq(1); - expect(stateVariables["/p4/cao"].stateValues.value).eq(1); - - expect(stateVariables["/cao"].stateValues.value).eq(0); - expect(stateVariables["/p2/ca"].stateValues.value).eq(0); - expect(stateVariables["/p3/cao"].stateValues.value).eq(0); - expect(stateVariables["/p4/ca"].stateValues.value).eq(0); - - expect(stateVariables["/m"].stateValues.value).eq("p"); - expect(stateVariables["/p2/m"].stateValues.value).eq("p"); - expect(stateVariables["/p3/m"].stateValues.value).eq("p"); - expect(stateVariables["/p4/m"].stateValues.value).eq("p"); - }); - - cy.log("correctly answer second problem"); - cy.get(mathinputp2Anchor).type("z{enter}", { force: true }); - cy.get(mathinputp2CorrectAnchor).should("be.visible"); - cy.get(mathinputp1CorrectAnchor).should("be.visible"); - cy.get(mathinputp3CorrectAnchor).should("be.visible"); - cy.get(mathinputp4CorrectAnchor).should("be.visible"); - - cy.get(mathinputp2FieldAnchor) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "z", - ); - }); - cy.get(mathinputp1FieldAnchor).should("have.text", "y"); - cy.get(mathinputp3FieldAnchor).should("have.text", "y"); - cy.get(mathinputp4FieldAnchor).should("have.text", "z"); - - cy.get(cesc2("#/ca")).contains("1"); - cy.get(cesc2("#/p2/cao")).contains("1"); - cy.get(cesc2("#/p3/ca")).contains("1"); - cy.get(cesc2("#/p4/cao")).contains("1"); - - cy.get(cesc2("#/cao")).contains("1"); - cy.get(cesc2("#/p2/ca")).contains("1"); - cy.get(cesc2("#/p3/cao")).contains("1"); - cy.get(cesc2("#/p4/ca")).contains("1"); - - cy.get(cesc2("#/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p2/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p3/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p4/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ca"].stateValues.value).eq(1); - expect(stateVariables["/p2/cao"].stateValues.value).eq(1); - expect(stateVariables["/p3/ca"].stateValues.value).eq(1); - expect(stateVariables["/p4/cao"].stateValues.value).eq(1); - - expect(stateVariables["/cao"].stateValues.value).eq(1); - expect(stateVariables["/p2/ca"].stateValues.value).eq(1); - expect(stateVariables["/p3/cao"].stateValues.value).eq(1); - expect(stateVariables["/p4/ca"].stateValues.value).eq(1); - - expect(stateVariables["/m"].stateValues.value).eq("p"); - expect(stateVariables["/p2/m"].stateValues.value).eq("p"); - expect(stateVariables["/p3/m"].stateValues.value).eq("p"); - expect(stateVariables["/p4/m"].stateValues.value).eq("p"); - }); - - cy.log("incorrectly answer third problem"); - cy.get(mathinputp3Anchor).type("{end}{backspace}a{enter}", { - force: true, - }); - cy.get(mathinputp3IncorrectAnchor).should("be.visible"); - cy.get(mathinputp1IncorrectAnchor).should("be.visible"); - cy.get(mathinputp2CorrectAnchor).should("be.visible"); - cy.get(mathinputp4CorrectAnchor).should("be.visible"); - - cy.get(mathinputp3FieldAnchor) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "a", - ); - }); - cy.get(mathinputp1FieldAnchor).should("have.text", "a"); - cy.get(mathinputp2FieldAnchor).should("have.text", "z"); - cy.get(mathinputp4FieldAnchor).should("have.text", "z"); - - cy.get(cesc2("#/ca")).contains("0"); - cy.get(cesc2("#/p2/cao")).contains("0"); - cy.get(cesc2("#/p3/ca")).contains("0"); - cy.get(cesc2("#/p4/cao")).contains("0"); - - cy.get(cesc2("#/cao")).contains("1"); - cy.get(cesc2("#/p2/ca")).contains("1"); - cy.get(cesc2("#/p3/cao")).contains("1"); - cy.get(cesc2("#/p4/ca")).contains("1"); - - cy.get(cesc2("#/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p2/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p3/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p4/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ca"].stateValues.value).eq(0); - expect(stateVariables["/p2/cao"].stateValues.value).eq(0); - expect(stateVariables["/p3/ca"].stateValues.value).eq(0); - expect(stateVariables["/p4/cao"].stateValues.value).eq(0); - - expect(stateVariables["/cao"].stateValues.value).eq(1); - expect(stateVariables["/p2/ca"].stateValues.value).eq(1); - expect(stateVariables["/p3/cao"].stateValues.value).eq(1); - expect(stateVariables["/p4/ca"].stateValues.value).eq(1); - - expect(stateVariables["/m"].stateValues.value).eq("p"); - expect(stateVariables["/p2/m"].stateValues.value).eq("p"); - expect(stateVariables["/p3/m"].stateValues.value).eq("p"); - expect(stateVariables["/p4/m"].stateValues.value).eq("p"); - }); - - cy.log("incorrectly answer fourth problem"); - cy.get(mathinputp4Anchor).type("{end}{backspace}b{enter}", { - force: true, - }); - cy.get(mathinputp4IncorrectAnchor).should("be.visible"); - cy.get(mathinputp1IncorrectAnchor).should("be.visible"); - cy.get(mathinputp2IncorrectAnchor).should("be.visible"); - cy.get(mathinputp3IncorrectAnchor).should("be.visible"); - - cy.get(mathinputp4FieldAnchor) - .invoke("text") - .then((text) => { - expect(text.replace(/[\s\u200B-\u200D\uFEFF]/g, "")).equal( - "b", - ); - }); - cy.get(mathinputp1FieldAnchor).should("have.text", "a"); - cy.get(mathinputp2FieldAnchor).should("have.text", "b"); - cy.get(mathinputp3FieldAnchor).should("have.text", "a"); - - cy.get(cesc2("#/ca")).contains("0"); - cy.get(cesc2("#/p2/cao")).contains("0"); - cy.get(cesc2("#/p3/ca")).contains("0"); - cy.get(cesc2("#/p4/cao")).contains("0"); - - cy.get(cesc2("#/cao")).contains("0"); - cy.get(cesc2("#/p2/ca")).contains("0"); - cy.get(cesc2("#/p3/cao")).contains("0"); - cy.get(cesc2("#/p4/ca")).contains("0"); - - cy.get(cesc2("#/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p2/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p3/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - cy.get(cesc2("#/p4/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "p"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ca"].stateValues.value).eq(0); - expect(stateVariables["/p2/cao"].stateValues.value).eq(0); - expect(stateVariables["/p3/ca"].stateValues.value).eq(0); - expect(stateVariables["/p4/cao"].stateValues.value).eq(0); - - expect(stateVariables["/cao"].stateValues.value).eq(0); - expect(stateVariables["/p2/ca"].stateValues.value).eq(0); - expect(stateVariables["/p3/cao"].stateValues.value).eq(0); - expect(stateVariables["/p4/ca"].stateValues.value).eq(0); - - expect(stateVariables["/m"].stateValues.value).eq("p"); - expect(stateVariables["/p2/m"].stateValues.value).eq("p"); - expect(stateVariables["/p3/m"].stateValues.value).eq("p"); - expect(stateVariables["/p4/m"].stateValues.value).eq("p"); - }); - - cy.log("change mathinput"); - cy.get(cesc2("#/mi") + " textarea").type( - "{end}{backspace}q{enter}", - { - force: true, - }, - ); - cy.get(cesc2("#/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "q"); - cy.get(cesc2("#/p2/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "q"); - cy.get(cesc2("#/p3/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "q"); - cy.get(cesc2("#/p4/m") + " .mjx-mrow") - .eq(0) - .should("have.text", "q"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/m"].stateValues.value).eq("q"); - expect(stateVariables["/p2/m"].stateValues.value).eq("q"); - expect(stateVariables["/p3/m"].stateValues.value).eq("q"); - expect(stateVariables["/p4/m"].stateValues.value).eq("q"); - }); - }); - }); - - it("copySource of map", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - -

Value:

-

Value 2:

- - - - - - - - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/n2")).contains("2"); - cy.get(cesc2("#/n3")).contains("2"); - - cy.get(cesc2("#/p1")).contains("Hello 1!"); - cy.get(cesc2("#/p1/_number1")).contains("1"); - cy.get(cesc2("#/p1/_math1")).contains("_"); - cy.get(cesc2("#/p2")).contains("Hello 2!"); - cy.get(cesc2("#/p2/_number1")).contains("2"); - cy.get(cesc2("#/p2/_math1")).contains("_"); - cy.get(cesc2("#/p3")).should("not.exist"); - cy.get(cesc2("#/p3/_number1")).should("not.exist"); - cy.get(cesc2("#/p3/_math1")).should("not.exist"); - - cy.get(cesc2("#/p1a")).contains("Hello 1!"); - cy.get(cesc2("#/p1a/_number1")).contains("1"); - cy.get(cesc2("#/p1a/_math1")).contains("_"); - cy.get(cesc2("#/p2a")).contains("Hello 2!"); - cy.get(cesc2("#/p2a/_number1")).contains("2"); - cy.get(cesc2("#/p2a/_math1")).contains("_"); - cy.get(cesc2("#/p3a")).should("not.exist"); - cy.get(cesc2("#/p3a/_number1")).should("not.exist"); - cy.get(cesc2("#/p3a/_math1")).should("not.exist"); - - cy.get(cesc2("#/p1b")).contains("Hello 1!"); - cy.get(cesc2("#/p1b/_number1")).contains("1"); - cy.get(cesc2("#/p1b/_math1")).contains("_"); - cy.get(cesc2("#/p2b")).contains("Hello 2!"); - cy.get(cesc2("#/p2b/_number1")).contains("2"); - cy.get(cesc2("#/p2b/_math1")).contains("_"); - cy.get(cesc2("#/p3b")).should("not.exist"); - cy.get(cesc2("#/p3b/_number1")).should("not.exist"); - cy.get(cesc2("#/p3b/_math1")).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/n2"].stateValues.value).eq(2); - expect(stateVariables["/n3"].stateValues.value).eq(2); - - expect(stateVariables["/p1/_number1"].stateValues.value).eq(1); - expect(stateVariables["/p2/_number1"].stateValues.value).eq(2); - expect(stateVariables["/p3/_number1"]).eq(undefined); - expect(stateVariables["/p1a/_number1"].stateValues.value).eq(1); - expect(stateVariables["/p2a/_number1"].stateValues.value).eq(2); - expect(stateVariables["/p3a/_number1"]).eq(undefined); - expect(stateVariables["/p1b/_number1"].stateValues.value).eq(1); - expect(stateVariables["/p2b/_number1"].stateValues.value).eq(2); - expect(stateVariables["/p3b/_number1"]).eq(undefined); - - expect(stateVariables["/p1/_math1"].stateValues.value).eq("_"); - expect(stateVariables["/p2/_math1"].stateValues.value).eq("_"); - expect(stateVariables["/p3/_math1"]).eq(undefined); - expect(stateVariables["/p1a/_math1"].stateValues.value).eq("_"); - expect(stateVariables["/p2a/_math1"].stateValues.value).eq("_"); - expect(stateVariables["/p3a/_math1"]).eq(undefined); - expect(stateVariables["/p1b/_math1"].stateValues.value).eq("_"); - expect(stateVariables["/p2b/_math1"].stateValues.value).eq("_"); - expect(stateVariables["/p3b/_math1"]).eq(undefined); - }); - - cy.log("type x in first mathinput"); - cy.get(cesc2("#/p1/x") + " textarea").type("x{enter}", { force: true }); - - cy.get(cesc2("#/p1")).contains("Hello 1!"); - cy.get(cesc2("#/p1/_number1")).contains("1"); - cy.get(cesc2("#/p1/_math1")).contains("x"); - cy.get(cesc2("#/p2")).contains("Hello 2!"); - cy.get(cesc2("#/p2/_number1")).contains("2"); - cy.get(cesc2("#/p2/_math1")).contains("_"); - cy.get(cesc2("#/p3")).should("not.exist"); - cy.get(cesc2("#/p3/_number1")).should("not.exist"); - cy.get(cesc2("#/p3/_math1")).should("not.exist"); - - cy.get(cesc2("#/p1a")).contains("Hello 1!"); - cy.get(cesc2("#/p1a/_number1")).contains("1"); - cy.get(cesc2("#/p1a/_math1")).contains("x"); - cy.get(cesc2("#/p2a")).contains("Hello 2!"); - cy.get(cesc2("#/p2a/_number1")).contains("2"); - cy.get(cesc2("#/p2a/_math1")).contains("_"); - cy.get(cesc2("#/p3a")).should("not.exist"); - cy.get(cesc2("#/p3a/_number1")).should("not.exist"); - cy.get(cesc2("#/p3a/_math1")).should("not.exist"); - - cy.get(cesc2("#/p1b")).contains("Hello 1!"); - cy.get(cesc2("#/p1b/_number1")).contains("1"); - cy.get(cesc2("#/p1b/_math1")).contains("x"); - cy.get(cesc2("#/p2b")).contains("Hello 2!"); - cy.get(cesc2("#/p2b/_number1")).contains("2"); - cy.get(cesc2("#/p2b/_math1")).contains("_"); - cy.get(cesc2("#/p3b")).should("not.exist"); - cy.get(cesc2("#/p3b/_number1")).should("not.exist"); - cy.get(cesc2("#/p3b/_math1")).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/n2"].stateValues.value).eq(2); - expect(stateVariables["/n3"].stateValues.value).eq(2); - - expect(stateVariables["/p1/_number1"].stateValues.value).eq(1); - expect(stateVariables["/p2/_number1"].stateValues.value).eq(2); - expect(stateVariables["/p3/_number1"]).eq(undefined); - expect(stateVariables["/p1a/_number1"].stateValues.value).eq(1); - expect(stateVariables["/p2a/_number1"].stateValues.value).eq(2); - expect(stateVariables["/p3a/_number1"]).eq(undefined); - expect(stateVariables["/p1b/_number1"].stateValues.value).eq(1); - expect(stateVariables["/p2b/_number1"].stateValues.value).eq(2); - expect(stateVariables["/p3b/_number1"]).eq(undefined); - - expect(stateVariables["/p1/_math1"].stateValues.value).eq("x"); - expect(stateVariables["/p2/_math1"].stateValues.value).eq("_"); - expect(stateVariables["/p3/_math1"]).eq(undefined); - expect(stateVariables["/p1a/_math1"].stateValues.value).eq("x"); - expect(stateVariables["/p2a/_math1"].stateValues.value).eq("_"); - expect(stateVariables["/p3a/_math1"]).eq(undefined); - expect(stateVariables["/p1b/_math1"].stateValues.value).eq("x"); - expect(stateVariables["/p2b/_math1"].stateValues.value).eq("_"); - expect(stateVariables["/p3b/_math1"]).eq(undefined); - }); - - cy.log("type y in second mathinput"); - cy.get(cesc2("#/p2b/x") + " textarea").type("y{enter}", { - force: true, - }); - - cy.get(cesc2("#/p1")).contains("Hello 1!"); - cy.get(cesc2("#/p1/_number1")).contains("1"); - cy.get(cesc2("#/p1/_math1")).contains("x"); - cy.get(cesc2("#/p2")).contains("Hello 2!"); - cy.get(cesc2("#/p2/_number1")).contains("2"); - cy.get(cesc2("#/p2/_math1")).contains("y"); - cy.get(cesc2("#/p3")).should("not.exist"); - cy.get(cesc2("#/p3/_number1")).should("not.exist"); - cy.get(cesc2("#/p3/_math1")).should("not.exist"); - - cy.get(cesc2("#/p1a")).contains("Hello 1!"); - cy.get(cesc2("#/p1a/_number1")).contains("1"); - cy.get(cesc2("#/p1a/_math1")).contains("x"); - cy.get(cesc2("#/p2a")).contains("Hello 2!"); - cy.get(cesc2("#/p2a/_number1")).contains("2"); - cy.get(cesc2("#/p2a/_math1")).contains("y"); - cy.get(cesc2("#/p3a")).should("not.exist"); - cy.get(cesc2("#/p3a/_number1")).should("not.exist"); - cy.get(cesc2("#/p3a/_math1")).should("not.exist"); - - cy.get(cesc2("#/p1b")).contains("Hello 1!"); - cy.get(cesc2("#/p1b/_number1")).contains("1"); - cy.get(cesc2("#/p1b/_math1")).contains("x"); - cy.get(cesc2("#/p2b")).contains("Hello 2!"); - cy.get(cesc2("#/p2b/_number1")).contains("2"); - cy.get(cesc2("#/p2b/_math1")).contains("y"); - cy.get(cesc2("#/p3b")).should("not.exist"); - cy.get(cesc2("#/p3b/_number1")).should("not.exist"); - cy.get(cesc2("#/p3b/_math1")).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/n2"].stateValues.value).eq(2); - expect(stateVariables["/n3"].stateValues.value).eq(2); - - expect(stateVariables["/p1/_number1"].stateValues.value).eq(1); - expect(stateVariables["/p2/_number1"].stateValues.value).eq(2); - expect(stateVariables["/p3/_number1"]).eq(undefined); - expect(stateVariables["/p1a/_number1"].stateValues.value).eq(1); - expect(stateVariables["/p2a/_number1"].stateValues.value).eq(2); - expect(stateVariables["/p3a/_number1"]).eq(undefined); - expect(stateVariables["/p1b/_number1"].stateValues.value).eq(1); - expect(stateVariables["/p2b/_number1"].stateValues.value).eq(2); - expect(stateVariables["/p3b/_number1"]).eq(undefined); - - expect(stateVariables["/p1/_math1"].stateValues.value).eq("x"); - expect(stateVariables["/p2/_math1"].stateValues.value).eq("y"); - expect(stateVariables["/p3/_math1"]).eq(undefined); - expect(stateVariables["/p1a/_math1"].stateValues.value).eq("x"); - expect(stateVariables["/p2a/_math1"].stateValues.value).eq("y"); - expect(stateVariables["/p3a/_math1"]).eq(undefined); - expect(stateVariables["/p1b/_math1"].stateValues.value).eq("x"); - expect(stateVariables["/p2b/_math1"].stateValues.value).eq("y"); - expect(stateVariables["/p3b/_math1"]).eq(undefined); - }); - - cy.log("increase n"); - cy.get(cesc2("#/n") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - - cy.get(cesc2("#/n2")).contains("3"); - cy.get(cesc2("#/n3")).contains("3"); - - cy.get(cesc2("#/p1")).contains("Hello 1!"); - cy.get(cesc2("#/p1/_number1")).contains("1"); - cy.get(cesc2("#/p1/_math1")).contains("x"); - cy.get(cesc2("#/p2")).contains("Hello 2!"); - cy.get(cesc2("#/p2/_number1")).contains("2"); - cy.get(cesc2("#/p2/_math1")).contains("y"); - cy.get(cesc2("#/p3")).contains("Hello 3!"); - cy.get(cesc2("#/p3/_number1")).contains("3"); - cy.get(cesc2("#/p3/_math1")).contains("_"); - - cy.get(cesc2("#/p1a")).contains("Hello 1!"); - cy.get(cesc2("#/p1a/_number1")).contains("1"); - cy.get(cesc2("#/p1a/_math1")).contains("x"); - cy.get(cesc2("#/p2a")).contains("Hello 2!"); - cy.get(cesc2("#/p2a/_number1")).contains("2"); - cy.get(cesc2("#/p2a/_math1")).contains("y"); - cy.get(cesc2("#/p3a")).contains("Hello 3!"); - cy.get(cesc2("#/p3a/_number1")).contains("3"); - cy.get(cesc2("#/p3a/_math1")).contains("_"); - - cy.get(cesc2("#/p1b")).contains("Hello 1!"); - cy.get(cesc2("#/p1b/_number1")).contains("1"); - cy.get(cesc2("#/p1b/_math1")).contains("x"); - cy.get(cesc2("#/p2b")).contains("Hello 2!"); - cy.get(cesc2("#/p2b/_number1")).contains("2"); - cy.get(cesc2("#/p2b/_math1")).contains("y"); - cy.get(cesc2("#/p3b")).contains("Hello 3!"); - cy.get(cesc2("#/p3b/_number1")).contains("3"); - cy.get(cesc2("#/p3b/_math1")).contains("_"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/n2"].stateValues.value).eq(3); - expect(stateVariables["/n3"].stateValues.value).eq(3); - - expect(stateVariables["/p1/_number1"].stateValues.value).eq(1); - expect(stateVariables["/p2/_number1"].stateValues.value).eq(2); - expect(stateVariables["/p3/_number1"].stateValues.value).eq(3); - expect(stateVariables["/p1a/_number1"].stateValues.value).eq(1); - expect(stateVariables["/p2a/_number1"].stateValues.value).eq(2); - expect(stateVariables["/p3a/_number1"].stateValues.value).eq(3); - expect(stateVariables["/p1b/_number1"].stateValues.value).eq(1); - expect(stateVariables["/p2b/_number1"].stateValues.value).eq(2); - expect(stateVariables["/p3b/_number1"].stateValues.value).eq(3); - - expect(stateVariables["/p1/_math1"].stateValues.value).eq("x"); - expect(stateVariables["/p2/_math1"].stateValues.value).eq("y"); - expect(stateVariables["/p3/_math1"].stateValues.value).eq("_"); - expect(stateVariables["/p1a/_math1"].stateValues.value).eq("x"); - expect(stateVariables["/p2a/_math1"].stateValues.value).eq("y"); - expect(stateVariables["/p3a/_math1"].stateValues.value).eq("_"); - expect(stateVariables["/p1b/_math1"].stateValues.value).eq("x"); - expect(stateVariables["/p2b/_math1"].stateValues.value).eq("y"); - expect(stateVariables["/p3b/_math1"].stateValues.value).eq("_"); - }); - - cy.log("type z in third mathinput"); - cy.get(cesc2("#/p3a/x") + " textarea").type("z{enter}", { - force: true, - }); - - cy.get(cesc2("#/p1")).contains("Hello 1!"); - cy.get(cesc2("#/p1/_number1")).contains("1"); - cy.get(cesc2("#/p1/_math1")).contains("x"); - cy.get(cesc2("#/p2")).contains("Hello 2!"); - cy.get(cesc2("#/p2/_number1")).contains("2"); - cy.get(cesc2("#/p2/_math1")).contains("y"); - cy.get(cesc2("#/p3")).contains("Hello 3!"); - cy.get(cesc2("#/p3/_number1")).contains("3"); - cy.get(cesc2("#/p3/_math1")).contains("z"); - - cy.get(cesc2("#/p1a")).contains("Hello 1!"); - cy.get(cesc2("#/p1a/_number1")).contains("1"); - cy.get(cesc2("#/p1a/_math1")).contains("x"); - cy.get(cesc2("#/p2a")).contains("Hello 2!"); - cy.get(cesc2("#/p2a/_number1")).contains("2"); - cy.get(cesc2("#/p2a/_math1")).contains("y"); - cy.get(cesc2("#/p3a")).contains("Hello 3!"); - cy.get(cesc2("#/p3a/_number1")).contains("3"); - cy.get(cesc2("#/p3a/_math1")).contains("z"); - - cy.get(cesc2("#/p1b")).contains("Hello 1!"); - cy.get(cesc2("#/p1b/_number1")).contains("1"); - cy.get(cesc2("#/p1b/_math1")).contains("x"); - cy.get(cesc2("#/p2b")).contains("Hello 2!"); - cy.get(cesc2("#/p2b/_number1")).contains("2"); - cy.get(cesc2("#/p2b/_math1")).contains("y"); - cy.get(cesc2("#/p3b")).contains("Hello 3!"); - cy.get(cesc2("#/p3b/_number1")).contains("3"); - cy.get(cesc2("#/p3b/_math1")).contains("z"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/n2"].stateValues.value).eq(3); - expect(stateVariables["/n3"].stateValues.value).eq(3); - - expect(stateVariables["/p1/_number1"].stateValues.value).eq(1); - expect(stateVariables["/p2/_number1"].stateValues.value).eq(2); - expect(stateVariables["/p3/_number1"].stateValues.value).eq(3); - expect(stateVariables["/p1a/_number1"].stateValues.value).eq(1); - expect(stateVariables["/p2a/_number1"].stateValues.value).eq(2); - expect(stateVariables["/p3a/_number1"].stateValues.value).eq(3); - expect(stateVariables["/p1b/_number1"].stateValues.value).eq(1); - expect(stateVariables["/p2b/_number1"].stateValues.value).eq(2); - expect(stateVariables["/p3b/_number1"].stateValues.value).eq(3); - - expect(stateVariables["/p1/_math1"].stateValues.value).eq("x"); - expect(stateVariables["/p2/_math1"].stateValues.value).eq("y"); - expect(stateVariables["/p3/_math1"].stateValues.value).eq("z"); - expect(stateVariables["/p1a/_math1"].stateValues.value).eq("x"); - expect(stateVariables["/p2a/_math1"].stateValues.value).eq("y"); - expect(stateVariables["/p3a/_math1"].stateValues.value).eq("z"); - expect(stateVariables["/p1b/_math1"].stateValues.value).eq("x"); - expect(stateVariables["/p2b/_math1"].stateValues.value).eq("y"); - expect(stateVariables["/p3b/_math1"].stateValues.value).eq("z"); - }); - }); - - it("macro to copy map", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - -

Value: $n.value{assignNames="n2"}

-

Value 2: $n2{name="n3"}

- - - - - - - $map1{name="map2" assignNames="(p1a) (p2a) (p3a)"} - - $map2{name="map3" assignNames="(p1b) (p2b) (p3b)"} - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/n2")).contains("2"); - cy.get(cesc2("#/n3")).contains("2"); - - cy.get(cesc2("#/p1")).contains("Hello 1!"); - cy.get(cesc2("#/p1/n1")).contains("1"); - cy.get(cesc2("#/p1/m1")).contains("_"); - cy.get(cesc2("#/p2")).contains("Hello 2!"); - cy.get(cesc2("#/p2/n1")).contains("2"); - cy.get(cesc2("#/p2/m1")).contains("_"); - cy.get(cesc2("#/p3")).should("not.exist"); - cy.get(cesc2("#/p3/n1")).should("not.exist"); - cy.get(cesc2("#/p3/m1")).should("not.exist"); - - cy.get(cesc2("#/p1a")).contains("Hello 1!"); - cy.get(cesc2("#/p1a/n1")).contains("1"); - cy.get(cesc2("#/p1a/m1")).contains("_"); - cy.get(cesc2("#/p2a")).contains("Hello 2!"); - cy.get(cesc2("#/p2a/n1")).contains("2"); - cy.get(cesc2("#/p2a/m1")).contains("_"); - cy.get(cesc2("#/p3a")).should("not.exist"); - cy.get(cesc2("#/p3a/n1")).should("not.exist"); - cy.get(cesc2("#/p3a/m1")).should("not.exist"); - - cy.get(cesc2("#/p1b")).contains("Hello 1!"); - cy.get(cesc2("#/p1b/n1")).contains("1"); - cy.get(cesc2("#/p1b/m1")).contains("_"); - cy.get(cesc2("#/p2b")).contains("Hello 2!"); - cy.get(cesc2("#/p2b/n1")).contains("2"); - cy.get(cesc2("#/p2b/m1")).contains("_"); - cy.get(cesc2("#/p3b")).should("not.exist"); - cy.get(cesc2("#/p3b/n1")).should("not.exist"); - cy.get(cesc2("#/p3b/m1")).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/n2"].stateValues.value).eq(2); - expect(stateVariables["/n3"].stateValues.value).eq(2); - - expect(stateVariables["/p1/n1"].stateValues.value).eq(1); - expect(stateVariables["/p2/n1"].stateValues.value).eq(2); - expect(stateVariables["/p3/n1"]).eq(undefined); - expect(stateVariables["/p1a/n1"].stateValues.value).eq(1); - expect(stateVariables["/p2a/n1"].stateValues.value).eq(2); - expect(stateVariables["/p3a/n1"]).eq(undefined); - expect(stateVariables["/p1b/n1"].stateValues.value).eq(1); - expect(stateVariables["/p2b/n1"].stateValues.value).eq(2); - expect(stateVariables["/p3b/n1"]).eq(undefined); - - expect(stateVariables["/p1/m1"].stateValues.value).eq("_"); - expect(stateVariables["/p2/m1"].stateValues.value).eq("_"); - expect(stateVariables["/p3/m1"]).eq(undefined); - expect(stateVariables["/p1a/m1"].stateValues.value).eq("_"); - expect(stateVariables["/p2a/m1"].stateValues.value).eq("_"); - expect(stateVariables["/p3a/m1"]).eq(undefined); - expect(stateVariables["/p1b/m1"].stateValues.value).eq("_"); - expect(stateVariables["/p2b/m1"].stateValues.value).eq("_"); - expect(stateVariables["/p3b/m1"]).eq(undefined); - }); - - cy.log("type x in first mathinput"); - cy.get(cesc2("#/p1/x") + " textarea").type("x{enter}", { force: true }); - - cy.get(cesc2("#/p1")).contains("Hello 1!"); - cy.get(cesc2("#/p1/n1")).contains("1"); - cy.get(cesc2("#/p1/m1")).contains("x"); - cy.get(cesc2("#/p2")).contains("Hello 2!"); - cy.get(cesc2("#/p2/n1")).contains("2"); - cy.get(cesc2("#/p2/m1")).contains("_"); - cy.get(cesc2("#/p3")).should("not.exist"); - cy.get(cesc2("#/p3/n1")).should("not.exist"); - cy.get(cesc2("#/p3/m1")).should("not.exist"); - - cy.get(cesc2("#/p1a")).contains("Hello 1!"); - cy.get(cesc2("#/p1a/n1")).contains("1"); - cy.get(cesc2("#/p1a/m1")).contains("x"); - cy.get(cesc2("#/p2a")).contains("Hello 2!"); - cy.get(cesc2("#/p2a/n1")).contains("2"); - cy.get(cesc2("#/p2a/m1")).contains("_"); - cy.get(cesc2("#/p3a")).should("not.exist"); - cy.get(cesc2("#/p3a/n1")).should("not.exist"); - cy.get(cesc2("#/p3a/m1")).should("not.exist"); - - cy.get(cesc2("#/p1b")).contains("Hello 1!"); - cy.get(cesc2("#/p1b/n1")).contains("1"); - cy.get(cesc2("#/p1b/m1")).contains("x"); - cy.get(cesc2("#/p2b")).contains("Hello 2!"); - cy.get(cesc2("#/p2b/n1")).contains("2"); - cy.get(cesc2("#/p2b/m1")).contains("_"); - cy.get(cesc2("#/p3b")).should("not.exist"); - cy.get(cesc2("#/p3b/n1")).should("not.exist"); - cy.get(cesc2("#/p3b/m1")).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/n2"].stateValues.value).eq(2); - expect(stateVariables["/n3"].stateValues.value).eq(2); - - expect(stateVariables["/p1/n1"].stateValues.value).eq(1); - expect(stateVariables["/p2/n1"].stateValues.value).eq(2); - expect(stateVariables["/p3/n1"]).eq(undefined); - expect(stateVariables["/p1a/n1"].stateValues.value).eq(1); - expect(stateVariables["/p2a/n1"].stateValues.value).eq(2); - expect(stateVariables["/p3a/n1"]).eq(undefined); - expect(stateVariables["/p1b/n1"].stateValues.value).eq(1); - expect(stateVariables["/p2b/n1"].stateValues.value).eq(2); - expect(stateVariables["/p3b/n1"]).eq(undefined); - - expect(stateVariables["/p1/m1"].stateValues.value).eq("x"); - expect(stateVariables["/p2/m1"].stateValues.value).eq("_"); - expect(stateVariables["/p3/m1"]).eq(undefined); - expect(stateVariables["/p1a/m1"].stateValues.value).eq("x"); - expect(stateVariables["/p2a/m1"].stateValues.value).eq("_"); - expect(stateVariables["/p3a/m1"]).eq(undefined); - expect(stateVariables["/p1b/m1"].stateValues.value).eq("x"); - expect(stateVariables["/p2b/m1"].stateValues.value).eq("_"); - expect(stateVariables["/p3b/m1"]).eq(undefined); - }); - - cy.log("type y in second mathinput"); - cy.get(cesc2("#/p2b/x") + " textarea").type("y{enter}", { - force: true, - }); - - cy.get(cesc2("#/p1")).contains("Hello 1!"); - cy.get(cesc2("#/p1/n1")).contains("1"); - cy.get(cesc2("#/p1/m1")).contains("x"); - cy.get(cesc2("#/p2")).contains("Hello 2!"); - cy.get(cesc2("#/p2/n1")).contains("2"); - cy.get(cesc2("#/p2/m1")).contains("y"); - cy.get(cesc2("#/p3")).should("not.exist"); - cy.get(cesc2("#/p3/n1")).should("not.exist"); - cy.get(cesc2("#/p3/m1")).should("not.exist"); - - cy.get(cesc2("#/p1a")).contains("Hello 1!"); - cy.get(cesc2("#/p1a/n1")).contains("1"); - cy.get(cesc2("#/p1a/m1")).contains("x"); - cy.get(cesc2("#/p2a")).contains("Hello 2!"); - cy.get(cesc2("#/p2a/n1")).contains("2"); - cy.get(cesc2("#/p2a/m1")).contains("y"); - cy.get(cesc2("#/p3a")).should("not.exist"); - cy.get(cesc2("#/p3a/n1")).should("not.exist"); - cy.get(cesc2("#/p3a/m1")).should("not.exist"); - - cy.get(cesc2("#/p1b")).contains("Hello 1!"); - cy.get(cesc2("#/p1b/n1")).contains("1"); - cy.get(cesc2("#/p1b/m1")).contains("x"); - cy.get(cesc2("#/p2b")).contains("Hello 2!"); - cy.get(cesc2("#/p2b/n1")).contains("2"); - cy.get(cesc2("#/p2b/m1")).contains("y"); - cy.get(cesc2("#/p3b")).should("not.exist"); - cy.get(cesc2("#/p3b/n1")).should("not.exist"); - cy.get(cesc2("#/p3b/m1")).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/n2"].stateValues.value).eq(2); - expect(stateVariables["/n3"].stateValues.value).eq(2); - - expect(stateVariables["/p1/n1"].stateValues.value).eq(1); - expect(stateVariables["/p2/n1"].stateValues.value).eq(2); - expect(stateVariables["/p3/n1"]).eq(undefined); - expect(stateVariables["/p1a/n1"].stateValues.value).eq(1); - expect(stateVariables["/p2a/n1"].stateValues.value).eq(2); - expect(stateVariables["/p3a/n1"]).eq(undefined); - expect(stateVariables["/p1b/n1"].stateValues.value).eq(1); - expect(stateVariables["/p2b/n1"].stateValues.value).eq(2); - expect(stateVariables["/p3b/n1"]).eq(undefined); - - expect(stateVariables["/p1/m1"].stateValues.value).eq("x"); - expect(stateVariables["/p2/m1"].stateValues.value).eq("y"); - expect(stateVariables["/p3/m1"]).eq(undefined); - expect(stateVariables["/p1a/m1"].stateValues.value).eq("x"); - expect(stateVariables["/p2a/m1"].stateValues.value).eq("y"); - expect(stateVariables["/p3a/m1"]).eq(undefined); - expect(stateVariables["/p1b/m1"].stateValues.value).eq("x"); - expect(stateVariables["/p2b/m1"].stateValues.value).eq("y"); - expect(stateVariables["/p3b/m1"]).eq(undefined); - }); - - cy.log("increase n"); - cy.get(cesc2("#/n") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - - cy.get(cesc2("#/n2")).contains("3"); - cy.get(cesc2("#/n3")).contains("3"); - - cy.get(cesc2("#/p1")).contains("Hello 1!"); - cy.get(cesc2("#/p1/n1")).contains("1"); - cy.get(cesc2("#/p1/m1")).contains("x"); - cy.get(cesc2("#/p2")).contains("Hello 2!"); - cy.get(cesc2("#/p2/n1")).contains("2"); - cy.get(cesc2("#/p2/m1")).contains("y"); - cy.get(cesc2("#/p3")).contains("Hello 3!"); - cy.get(cesc2("#/p3/n1")).contains("3"); - cy.get(cesc2("#/p3/m1")).contains("_"); - - cy.get(cesc2("#/p1a")).contains("Hello 1!"); - cy.get(cesc2("#/p1a/n1")).contains("1"); - cy.get(cesc2("#/p1a/m1")).contains("x"); - cy.get(cesc2("#/p2a")).contains("Hello 2!"); - cy.get(cesc2("#/p2a/n1")).contains("2"); - cy.get(cesc2("#/p2a/m1")).contains("y"); - cy.get(cesc2("#/p3a")).contains("Hello 3!"); - cy.get(cesc2("#/p3a/n1")).contains("3"); - cy.get(cesc2("#/p3a/m1")).contains("_"); - - cy.get(cesc2("#/p1b")).contains("Hello 1!"); - cy.get(cesc2("#/p1b/n1")).contains("1"); - cy.get(cesc2("#/p1b/m1")).contains("x"); - cy.get(cesc2("#/p2b")).contains("Hello 2!"); - cy.get(cesc2("#/p2b/n1")).contains("2"); - cy.get(cesc2("#/p2b/m1")).contains("y"); - cy.get(cesc2("#/p3b")).contains("Hello 3!"); - cy.get(cesc2("#/p3b/n1")).contains("3"); - cy.get(cesc2("#/p3b/m1")).contains("_"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/n2"].stateValues.value).eq(3); - expect(stateVariables["/n3"].stateValues.value).eq(3); - - expect(stateVariables["/p1/n1"].stateValues.value).eq(1); - expect(stateVariables["/p2/n1"].stateValues.value).eq(2); - expect(stateVariables["/p3/n1"].stateValues.value).eq(3); - expect(stateVariables["/p1a/n1"].stateValues.value).eq(1); - expect(stateVariables["/p2a/n1"].stateValues.value).eq(2); - expect(stateVariables["/p3a/n1"].stateValues.value).eq(3); - expect(stateVariables["/p1b/n1"].stateValues.value).eq(1); - expect(stateVariables["/p2b/n1"].stateValues.value).eq(2); - expect(stateVariables["/p3b/n1"].stateValues.value).eq(3); - - expect(stateVariables["/p1/m1"].stateValues.value).eq("x"); - expect(stateVariables["/p2/m1"].stateValues.value).eq("y"); - expect(stateVariables["/p3/m1"].stateValues.value).eq("_"); - expect(stateVariables["/p1a/m1"].stateValues.value).eq("x"); - expect(stateVariables["/p2a/m1"].stateValues.value).eq("y"); - expect(stateVariables["/p3a/m1"].stateValues.value).eq("_"); - expect(stateVariables["/p1b/m1"].stateValues.value).eq("x"); - expect(stateVariables["/p2b/m1"].stateValues.value).eq("y"); - expect(stateVariables["/p3b/m1"].stateValues.value).eq("_"); - }); - - cy.log("type z in third mathinput"); - cy.get(cesc2("#/p3a/x") + " textarea").type("z{enter}", { - force: true, - }); - - cy.get(cesc2("#/p1")).contains("Hello 1!"); - cy.get(cesc2("#/p1/n1")).contains("1"); - cy.get(cesc2("#/p1/m1")).contains("x"); - cy.get(cesc2("#/p2")).contains("Hello 2!"); - cy.get(cesc2("#/p2/n1")).contains("2"); - cy.get(cesc2("#/p2/m1")).contains("y"); - cy.get(cesc2("#/p3")).contains("Hello 3!"); - cy.get(cesc2("#/p3/n1")).contains("3"); - cy.get(cesc2("#/p3/m1")).contains("z"); - - cy.get(cesc2("#/p1a")).contains("Hello 1!"); - cy.get(cesc2("#/p1a/n1")).contains("1"); - cy.get(cesc2("#/p1a/m1")).contains("x"); - cy.get(cesc2("#/p2a")).contains("Hello 2!"); - cy.get(cesc2("#/p2a/n1")).contains("2"); - cy.get(cesc2("#/p2a/m1")).contains("y"); - cy.get(cesc2("#/p3a")).contains("Hello 3!"); - cy.get(cesc2("#/p3a/n1")).contains("3"); - cy.get(cesc2("#/p3a/m1")).contains("z"); - - cy.get(cesc2("#/p1b")).contains("Hello 1!"); - cy.get(cesc2("#/p1b/n1")).contains("1"); - cy.get(cesc2("#/p1b/m1")).contains("x"); - cy.get(cesc2("#/p2b")).contains("Hello 2!"); - cy.get(cesc2("#/p2b/n1")).contains("2"); - cy.get(cesc2("#/p2b/m1")).contains("y"); - cy.get(cesc2("#/p3b")).contains("Hello 3!"); - cy.get(cesc2("#/p3b/n1")).contains("3"); - cy.get(cesc2("#/p3b/m1")).contains("z"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/n2"].stateValues.value).eq(3); - expect(stateVariables["/n3"].stateValues.value).eq(3); - - expect(stateVariables["/p1/n1"].stateValues.value).eq(1); - expect(stateVariables["/p2/n1"].stateValues.value).eq(2); - expect(stateVariables["/p3/n1"].stateValues.value).eq(3); - expect(stateVariables["/p1a/n1"].stateValues.value).eq(1); - expect(stateVariables["/p2a/n1"].stateValues.value).eq(2); - expect(stateVariables["/p3a/n1"].stateValues.value).eq(3); - expect(stateVariables["/p1b/n1"].stateValues.value).eq(1); - expect(stateVariables["/p2b/n1"].stateValues.value).eq(2); - expect(stateVariables["/p3b/n1"].stateValues.value).eq(3); - - expect(stateVariables["/p1/m1"].stateValues.value).eq("x"); - expect(stateVariables["/p2/m1"].stateValues.value).eq("y"); - expect(stateVariables["/p3/m1"].stateValues.value).eq("z"); - expect(stateVariables["/p1a/m1"].stateValues.value).eq("x"); - expect(stateVariables["/p2a/m1"].stateValues.value).eq("y"); - expect(stateVariables["/p3a/m1"].stateValues.value).eq("z"); - expect(stateVariables["/p1b/m1"].stateValues.value).eq("x"); - expect(stateVariables["/p2b/m1"].stateValues.value).eq("y"); - expect(stateVariables["/p3b/m1"].stateValues.value).eq("z"); - }); - }); - - it("copySource and createComponentOfType wrap to match specified type", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - $mi{name="m2" createComponentOfType="MatH"} - - - $mi{name="n2" createComponentOfType="number"} - - (x,y) - - - $P{name="c2" createComponentOfType="coords"} - - $P.coords{assignNames="c4" createComponentOfType="coords"} - - - $P{name="mc2" createComponentOfType="math"} - - $P.coords{assignNames="mc4" createComponentOfType="math"} - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/m1") + " .mjx-mrow") - .eq(0) - .contains("2"); - cy.get(cesc2("#/m2") + " .mjx-mrow") - .eq(0) - .contains("2"); - - cy.get(cesc2("#/n1")).contains("2"); - cy.get(cesc2("#/n2")).contains("2"); - - cy.get(cesc2("#/c1") + " .mjx-mrow") - .eq(0) - .contains("(x,y)"); - cy.get(cesc2("#/c2") + " .mjx-mrow") - .eq(0) - .contains("(x,y)"); - cy.get(cesc2("#/c3") + " .mjx-mrow") - .eq(0) - .contains("(x,y)"); - cy.get(cesc2("#/c4") + " .mjx-mrow") - .eq(0) - .contains("(x,y)"); - - cy.get(cesc2("#/mc1") + " .mjx-mrow") - .eq(0) - .contains("(x,y)"); - cy.get(cesc2("#/mc2") + " .mjx-mrow") - .eq(0) - .contains("(x,y)"); - cy.get(cesc2("#/mc3") + " .mjx-mrow") - .eq(0) - .contains("(x,y)"); - cy.get(cesc2("#/mc4") + " .mjx-mrow") - .eq(0) - .contains("(x,y)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/m1"].stateValues.value).eq(2); - expect(stateVariables["/m2"].stateValues.value).eq(2); - - expect(stateVariables["/n1"].stateValues.value).eq(2); - expect(stateVariables["/n2"].stateValues.value).eq(2); - - expect(stateVariables["/c1"].stateValues.value).eqls([ - "vector", - "x", - "y", - ]); - expect(stateVariables["/c2"].stateValues.value).eqls([ - "vector", - "x", - "y", - ]); - expect(stateVariables["/c3"].stateValues.value).eqls([ - "vector", - "x", - "y", - ]); - expect(stateVariables["/c4"].stateValues.value).eqls([ - "vector", - "x", - "y", - ]); - - expect(stateVariables["/mc1"].stateValues.value).eqls([ - "vector", - "x", - "y", - ]); - expect(stateVariables["/mc2"].stateValues.value).eqls([ - "vector", - "x", - "y", - ]); - expect(stateVariables["/mc3"].stateValues.value).eqls([ - "vector", - "x", - "y", - ]); - expect(stateVariables["/mc4"].stateValues.value).eqls([ - "vector", - "x", - "y", - ]); - }); - - cy.log("enter a"); - cy.get(cesc2("#/mi") + " textarea").type("{end}{backspace}a{enter}", { - force: true, - }); - - cy.get(cesc2("#/m1") + " .mjx-mrow").should("contain.text", "a"); - - cy.get(cesc2("#/m1") + " .mjx-mrow") - .eq(0) - .contains("a"); - cy.get(cesc2("#/m2") + " .mjx-mrow") - .eq(0) - .contains("a"); - - cy.get(cesc2("#/n1")).contains("NaN"); - cy.get(cesc2("#/n2")).contains("NaN"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/m1"].stateValues.value).eq("a"); - expect(stateVariables["/m2"].stateValues.value).eq("a"); - - expect(stateVariables["/n1"].stateValues.value).eqls(NaN); - expect(stateVariables["/n2"].stateValues.value).eqls(NaN); - }); - }); - - it("add children to invalid copySource", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/Pcoords") + " .mjx-mrow") - .eq(0) - .contains("(0,0)"); - cy.get(cesc2("#/g2Pcoords") + " .mjx-mrow") - .eq(0) - .contains("(0,0)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g"].activeChildren.length).eq(1); - expect(stateVariables["/g"].activeChildren[0].componentName).eq( - "/P", - ); - expect(stateVariables["/P"].stateValues.xs).eqls([0, 0]); - - expect(stateVariables["/g2"].activeChildren.length).eq(1); - expect(stateVariables["/g2"].activeChildren[0].componentName).eq( - "/g2/P", - ); - expect(stateVariables["/g2/P"].stateValues.xs).eqls([0, 0]); - - expect(stateVariables["/Pcoords"].stateValues.value).eqls([ - "vector", - 0, - 0, - ]); - expect(stateVariables["/g2Pcoords"].stateValues.value).eqls([ - "vector", - 0, - 0, - ]); - }); - - cy.log(`move points`); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 3, y: 5 }, - }); - win.callAction1({ - actionName: "movePoint", - componentName: "/g2/P", - args: { x: 7, y: 6 }, - }); - }); - - cy.get(cesc2("#/g2Pcoords") + " .mjx-mrow").should( - "contain.text", - "(7,6)", - ); - cy.get(cesc2("#/Pcoords") + " .mjx-mrow").should( - "contain.text", - "(3,5)", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.xs).eqls([3, 5]); - - expect(stateVariables["/g2/P"].stateValues.xs).eqls([7, 6]); - - expect(stateVariables["/Pcoords"].stateValues.value).eqls([ - "vector", - 3, - 5, - ]); - expect(stateVariables["/g2Pcoords"].stateValues.value).eqls([ - "vector", - 7, - 6, - ]); - }); - }); - - it("add children with copySource, different newNamespace combinations", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - (1,2) - - - - (4,5) - - - - - - - (1,2) - - - - (4,5) - - - - - - - - (1,2) - - - - (4,5) - - - - - - - - (1,2) - - - - (4,5) - - - - - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/P1coords") + " .mjx-mrow") - .eq(0) - .contains("(1,2)"); - cy.get(cesc2("#/v1displacement") + " .mjx-mrow") - .eq(0) - .contains("(4,5)"); - - cy.get(cesc2("#/P2coords") + " .mjx-mrow") - .eq(0) - .contains("(1,2)"); - cy.get(cesc2("#/P2acoords") + " .mjx-mrow") - .eq(0) - .contains("(1,2)"); - cy.get(cesc2("#/v2displacement") + " .mjx-mrow") - .eq(0) - .contains("(4,5)"); - - cy.get(cesc2("#/P3coords") + " .mjx-mrow") - .eq(0) - .contains("(1,2)"); - cy.get(cesc2("#/P3acoords") + " .mjx-mrow") - .eq(0) - .contains("(1,2)"); - cy.get(cesc2("#/v3displacement") + " .mjx-mrow") - .eq(0) - .contains("(4,5)"); - - cy.get(cesc2("#/P4coords") + " .mjx-mrow") - .eq(0) - .contains("(1,2)"); - cy.get(cesc2("#/P4acoords") + " .mjx-mrow") - .eq(0) - .contains("(1,2)"); - cy.get(cesc2("#/v4displacement") + " .mjx-mrow") - .eq(0) - .contains("(4,5)"); - - let P1aName; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g1"].activeChildren.length).eq(1); - expect(stateVariables["/g1"].activeChildren[0].componentName).eq( - "/P1", - ); - expect(stateVariables["/P1"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/g1a"].activeChildren.length).eq(2); - expect(stateVariables["/g1a"].activeChildren[1].componentName).eq( - "/v1", - ); - P1aName = stateVariables["/g1a"].activeChildren[0].componentName; - expect(stateVariables[P1aName].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/v1"].stateValues.displacement).eqls([4, 5]); - expect(stateVariables["/P1coords"].stateValues.value).eqls([ - "vector", - 1, - 2, - ]); - expect(stateVariables["/v1displacement"].stateValues.value).eqls([ - "vector", - 4, - 5, - ]); - - expect(stateVariables["/g2"].activeChildren.length).eq(1); - expect(stateVariables["/g2"].activeChildren[0].componentName).eq( - "/P2", - ); - expect(stateVariables["/P2"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/g2a"].activeChildren.length).eq(2); - expect(stateVariables["/g2a"].activeChildren[0].componentName).eq( - "/g2a/P2", - ); - expect(stateVariables["/g2a"].activeChildren[1].componentName).eq( - "/g2a/v2", - ); - expect(stateVariables["/g2a/P2"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/g2a/v2"].stateValues.displacement).eqls([ - 4, 5, - ]); - expect(stateVariables["/P2coords"].stateValues.value).eqls([ - "vector", - 1, - 2, - ]); - expect(stateVariables["/P2acoords"].stateValues.value).eqls([ - "vector", - 1, - 2, - ]); - expect(stateVariables["/v2displacement"].stateValues.value).eqls([ - "vector", - 4, - 5, - ]); - - expect(stateVariables["/g3"].activeChildren.length).eq(1); - expect(stateVariables["/g3"].activeChildren[0].componentName).eq( - "/g3/P3", - ); - expect(stateVariables["/g3/P3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/g3a"].activeChildren.length).eq(2); - expect(stateVariables["/g3a"].activeChildren[0].componentName).eq( - "/g3a/P3", - ); - expect(stateVariables["/g3a"].activeChildren[1].componentName).eq( - "/g3a/v3", - ); - expect(stateVariables["/g3a/P3"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/g3a/v3"].stateValues.displacement).eqls([ - 4, 5, - ]); - expect(stateVariables["/P3coords"].stateValues.value).eqls([ - "vector", - 1, - 2, - ]); - expect(stateVariables["/P3acoords"].stateValues.value).eqls([ - "vector", - 1, - 2, - ]); - expect(stateVariables["/v3displacement"].stateValues.value).eqls([ - "vector", - 4, - 5, - ]); - - expect(stateVariables["/g4"].activeChildren.length).eq(1); - expect(stateVariables["/g4"].activeChildren[0].componentName).eq( - "/g4/P4", - ); - expect(stateVariables["/g4/P4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/g4a"].activeChildren.length).eq(2); - expect(stateVariables["/g4a"].activeChildren[0].componentName).eq( - "/g4a/P4", - ); - expect(stateVariables["/g4a"].activeChildren[1].componentName).eq( - "/v4", - ); - expect(stateVariables["/g4a/P4"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/v4"].stateValues.displacement).eqls([4, 5]); - expect(stateVariables["/P4coords"].stateValues.value).eqls([ - "vector", - 1, - 2, - ]); - expect(stateVariables["/P4acoords"].stateValues.value).eqls([ - "vector", - 1, - 2, - ]); - expect(stateVariables["/v4displacement"].stateValues.value).eqls([ - "vector", - 4, - 5, - ]); - }); - - cy.log(`move points`); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/P1", - args: { x: 3, y: 5 }, - }); - win.callAction1({ - actionName: "moveVector", - componentName: "/v1", - args: { - headcoords: [8, 7], - }, - }); - win.callAction1({ - actionName: "movePoint", - componentName: "/P2", - args: { x: 6, y: 0 }, - }); - win.callAction1({ - actionName: "moveVector", - componentName: "/g2a/v2", - args: { - headcoords: [9, 1], - }, - }); - win.callAction1({ - actionName: "movePoint", - componentName: "/g3/P3", - args: { x: 5, y: 8 }, - }); - win.callAction1({ - actionName: "moveVector", - componentName: "/g3a/v3", - args: { - headcoords: [8, 6], - }, - }); - win.callAction1({ - actionName: "movePoint", - componentName: "/g4/P4", - args: { x: 0, y: 3 }, - }); - win.callAction1({ - actionName: "moveVector", - componentName: "/v4", - args: { - headcoords: [7, 2], - }, - }); - }); - - cy.get(cesc2("#/v4displacement") + " .mjx-mrow").should( - "contain.text", - "(7,2)", - ); - - cy.get(cesc2("#/P1coords") + " .mjx-mrow") - .eq(0) - .contains("(3,5)"); - cy.get(cesc2("#/v1displacement") + " .mjx-mrow") - .eq(0) - .contains("(8,7)"); - - cy.get(cesc2("#/P2coords") + " .mjx-mrow") - .eq(0) - .contains("(6,0)"); - cy.get(cesc2("#/P2acoords") + " .mjx-mrow") - .eq(0) - .contains("(6,0)"); - cy.get(cesc2("#/v2displacement") + " .mjx-mrow") - .eq(0) - .contains("(9,1)"); - - cy.get(cesc2("#/P3coords") + " .mjx-mrow") - .eq(0) - .contains("(5,8)"); - cy.get(cesc2("#/P3acoords") + " .mjx-mrow") - .eq(0) - .contains("(5,8)"); - cy.get(cesc2("#/v3displacement") + " .mjx-mrow") - .eq(0) - .contains("(8,6)"); - - cy.get(cesc2("#/P4coords") + " .mjx-mrow") - .eq(0) - .contains("(0,3)"); - cy.get(cesc2("#/P4acoords") + " .mjx-mrow") - .eq(0) - .contains("(0,3)"); - cy.get(cesc2("#/v4displacement") + " .mjx-mrow") - .eq(0) - .contains("(7,2)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P1"].stateValues.xs).eqls([3, 5]); - expect(stateVariables[P1aName].stateValues.xs).eqls([3, 5]); - expect(stateVariables["/v1"].stateValues.displacement).eqls([8, 7]); - expect(stateVariables["/P1coords"].stateValues.value).eqls([ - "vector", - 3, - 5, - ]); - expect(stateVariables["/v1displacement"].stateValues.value).eqls([ - "vector", - 8, - 7, - ]); - - expect(stateVariables["/P2"].stateValues.xs).eqls([6, 0]); - expect(stateVariables["/g2a/P2"].stateValues.xs).eqls([6, 0]); - expect(stateVariables["/g2a/v2"].stateValues.displacement).eqls([ - 9, 1, - ]); - expect(stateVariables["/P2coords"].stateValues.value).eqls([ - "vector", - 6, - 0, - ]); - expect(stateVariables["/P2acoords"].stateValues.value).eqls([ - "vector", - 6, - 0, - ]); - expect(stateVariables["/v2displacement"].stateValues.value).eqls([ - "vector", - 9, - 1, - ]); - - expect(stateVariables["/g3/P3"].stateValues.xs).eqls([5, 8]); - expect(stateVariables["/g3a/P3"].stateValues.xs).eqls([5, 8]); - expect(stateVariables["/g3a/v3"].stateValues.displacement).eqls([ - 8, 6, - ]); - expect(stateVariables["/P3coords"].stateValues.value).eqls([ - "vector", - 5, - 8, - ]); - expect(stateVariables["/P3acoords"].stateValues.value).eqls([ - "vector", - 5, - 8, - ]); - expect(stateVariables["/v3displacement"].stateValues.value).eqls([ - "vector", - 8, - 6, - ]); - - expect(stateVariables["/g4/P4"].stateValues.xs).eqls([0, 3]); - expect(stateVariables["/g4a/P4"].stateValues.xs).eqls([0, 3]); - expect(stateVariables["/v4"].stateValues.displacement).eqls([7, 2]); - expect(stateVariables["/P4coords"].stateValues.value).eqls([ - "vector", - 0, - 3, - ]); - expect(stateVariables["/P4acoords"].stateValues.value).eqls([ - "vector", - 0, - 3, - ]); - expect(stateVariables["/v4displacement"].stateValues.value).eqls([ - "vector", - 7, - 2, - ]); - }); - - cy.log(`move shadowed points`); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: P1aName, - args: { x: 2, y: 1 }, - }); - win.callAction1({ - actionName: "movePoint", - componentName: "/g2a/P2", - args: { x: 5, y: 4 }, - }); - win.callAction1({ - actionName: "movePoint", - componentName: "/g3a/P3", - args: { x: 9, y: 7 }, - }); - win.callAction1({ - actionName: "movePoint", - componentName: "/g4a/P4", - args: { x: 7, y: 6 }, - }); - }); - - cy.get(cesc2("#/P4coords") + " .mjx-mrow").should( - "contain.text", - "(7,6)", - ); - - cy.get(cesc2("#/P1coords") + " .mjx-mrow") - .eq(0) - .contains("(2,1)"); - cy.get(cesc2("#/v1displacement") + " .mjx-mrow") - .eq(0) - .contains("(8,7)"); - - cy.get(cesc2("#/P2coords") + " .mjx-mrow") - .eq(0) - .contains("(5,4)"); - cy.get(cesc2("#/P2acoords") + " .mjx-mrow") - .eq(0) - .contains("(5,4)"); - cy.get(cesc2("#/v2displacement") + " .mjx-mrow") - .eq(0) - .contains("(9,1)"); - - cy.get(cesc2("#/P3coords") + " .mjx-mrow") - .eq(0) - .contains("(9,7)"); - cy.get(cesc2("#/P3acoords") + " .mjx-mrow") - .eq(0) - .contains("(9,7)"); - cy.get(cesc2("#/v3displacement") + " .mjx-mrow") - .eq(0) - .contains("(8,6)"); - - cy.get(cesc2("#/P4coords") + " .mjx-mrow") - .eq(0) - .contains("(7,6)"); - cy.get(cesc2("#/P4acoords") + " .mjx-mrow") - .eq(0) - .contains("(7,6)"); - cy.get(cesc2("#/v4displacement") + " .mjx-mrow") - .eq(0) - .contains("(7,2)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P1"].stateValues.xs).eqls([2, 1]); - expect(stateVariables[P1aName].stateValues.xs).eqls([2, 1]); - expect(stateVariables["/v1"].stateValues.displacement).eqls([8, 7]); - expect(stateVariables["/P1coords"].stateValues.value).eqls([ - "vector", - 2, - 1, - ]); - expect(stateVariables["/v1displacement"].stateValues.value).eqls([ - "vector", - 8, - 7, - ]); - - expect(stateVariables["/P2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/g2a/P2"].stateValues.xs).eqls([5, 4]); - expect(stateVariables["/g2a/v2"].stateValues.displacement).eqls([ - 9, 1, - ]); - expect(stateVariables["/P2coords"].stateValues.value).eqls([ - "vector", - 5, - 4, - ]); - expect(stateVariables["/P2acoords"].stateValues.value).eqls([ - "vector", - 5, - 4, - ]); - expect(stateVariables["/v2displacement"].stateValues.value).eqls([ - "vector", - 9, - 1, - ]); - - expect(stateVariables["/g3/P3"].stateValues.xs).eqls([9, 7]); - expect(stateVariables["/g3a/P3"].stateValues.xs).eqls([9, 7]); - expect(stateVariables["/g3a/v3"].stateValues.displacement).eqls([ - 8, 6, - ]); - expect(stateVariables["/P3coords"].stateValues.value).eqls([ - "vector", - 9, - 7, - ]); - expect(stateVariables["/P3acoords"].stateValues.value).eqls([ - "vector", - 9, - 7, - ]); - expect(stateVariables["/v3displacement"].stateValues.value).eqls([ - "vector", - 8, - 6, - ]); - - expect(stateVariables["/g4/P4"].stateValues.xs).eqls([7, 6]); - expect(stateVariables["/g4a/P4"].stateValues.xs).eqls([7, 6]); - expect(stateVariables["/v4"].stateValues.displacement).eqls([7, 2]); - expect(stateVariables["/P4coords"].stateValues.value).eqls([ - "vector", - 7, - 6, - ]); - expect(stateVariables["/P4acoords"].stateValues.value).eqls([ - "vector", - 7, - 6, - ]); - expect(stateVariables["/v4displacement"].stateValues.value).eqls([ - "vector", - 7, - 2, - ]); - }); - }); - - it("add children with copySource, ignore implicit newNamespace when copied", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - (1,2) - - - - - - - - - - - - - - -

Point 1:

-

Point 2:

-

Vector 2:

-

Point 3:

-

Vector 3:

-

Point 4:

-

Nothing at g4/v:

- - -

Grp2 Point 1:

-

Grp2 Point 2:

- -

Grp2 Vector 2:

-

Nothing at /grp2/g2/v:

- -

Grp2 Point 3:

-

Grp2 Vector 3:

- -

Grp2 Point 4:

-

Nothing at /grp2/g4/v:

-
- - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/P1coords") + " .mjx-mrow") - .eq(0) - .contains("(1,2)"); - cy.get(cesc2("#/P2coords") + " .mjx-mrow") - .eq(0) - .contains("(1,2)"); - cy.get(cesc2("#/v2displacement") + " .mjx-mrow") - .eq(0) - .contains("(1,0)"); - cy.get(cesc2("#/P3coords") + " .mjx-mrow") - .eq(0) - .contains("(1,2)"); - cy.get(cesc2("#/v3displacement") + " .mjx-mrow") - .eq(0) - .contains("(1,0)"); - cy.get(cesc2("#/P4coords") + " .mjx-mrow") - .eq(0) - .contains("(1,2)"); - cy.get(cesc2("#/v4nodisplacement") + " .mjx-mrow") - .eq(0) - .contains("\uff3f"); - - cy.get(cesc2("#/grp2ps/P1coords") + " .mjx-mrow") - .eq(0) - .contains("(1,2)"); - cy.get(cesc2("#/grp2ps/P2coords") + " .mjx-mrow") - .eq(0) - .contains("(1,2)"); - cy.get(cesc2("#/grp2ps/v2displacement") + " .mjx-mrow") - .eq(0) - .contains("(1,0)"); - cy.get(cesc2("#/grp2ps/v2nodisplacement") + " .mjx-mrow") - .eq(0) - .contains("\uff3f"); - cy.get(cesc2("#/grp2ps/P3coords") + " .mjx-mrow") - .eq(0) - .contains("(1,2)"); - cy.get(cesc2("#/grp2ps/v3displacement") + " .mjx-mrow") - .eq(0) - .contains("(1,0)"); - cy.get(cesc2("#/grp2ps/P4coords") + " .mjx-mrow") - .eq(0) - .contains("(1,2)"); - cy.get(cesc2("#/grp2ps/v4nodisplacement") + " .mjx-mrow") - .eq(0) - .contains("\uff3f"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g/P"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/g2/P"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/v"].stateValues.displacement).eqls([1, 0]); - expect(stateVariables["/g3/P"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/g3/v"].stateValues.displacement).eqls([ - 1, 0, - ]); - expect(stateVariables["/g4/P"].stateValues.xs).eqls([1, 2]); - let g4vName = stateVariables["/g4"].activeChildren[1].componentName; - expect(g4vName.substring(0, 3) === "/__"); - expect(stateVariables[g4vName].stateValues.displacement).eqls([ - 1, 0, - ]); - expect(stateVariables["/g4/v"]).eq(undefined); - - expect(stateVariables["/grp2/g/P"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/grp2/g2/P"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/grp2/v"].stateValues.displacement).eqls([ - 1, 0, - ]); - expect(stateVariables["/grp2/g2/v"]).eq(undefined); - expect(stateVariables["/grp2/g3/P"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/grp2/g3/v"].stateValues.displacement).eqls([ - 1, 0, - ]); - expect(stateVariables["/grp2/g4/P"].stateValues.xs).eqls([1, 2]); - let grp2g4vName = - stateVariables["/grp2/g4"].activeChildren[1].componentName; - expect(grp2g4vName.substring(0, 3) === "/__"); - expect(stateVariables[grp2g4vName].stateValues.displacement).eqls([ - 1, 0, - ]); - expect(stateVariables["/grp2/g4/v"]).eq(undefined); - }); - }); - - it("add children with copySource, multiple levels of groups", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - (1,2) - - - - (4,5) - - - - - - - - $g{name="g4"} - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Point 1:

-

Point 2:

-

Vector 2:

-

Point 3:

-

Vector 3:

-

Circle 3 center:

-

Line segment 3 point 1:

-

Line segment 3 point 2:

-

Point 4:

-

Point 5:

-

Circle 5 center:

- - -

Grp2 Point 1:

-

Grp2 Point 2:

-

Grp2 Vector 2:

-

Grp2 Point 3:

-

Grp2 Vector 3:

-

Grp2 Circle 3 center:

-

Grp2 Line segment 3 point 1:

-

Grp2 Line segment 3 point 2:

-

Grp2 Point 4:

-

Grp2 Point 5:

-

Grp2 Circle 5 center:

-

Grp2 Point 6:

-

Grp2 Circle 6 center:

-

Grp2 Line segment 6 point 1:

-

Grp2 Line segment 6 point 2:

-
- - - - -

Grp3 Point 1:

-

Grp3 Point 2:

-

Grp3 Vector 2:

-

Grp3 Point 3:

-

Grp3 Vector 3:

-

Grp3 Circle 3 center:

-

Grp3 Line segment 3 point 1:

-

Grp3 Line segment 3 point 2:

-

Grp3 Point 4:

-

Grp3 Point 5:

-

Grp3 Circle 5 center:

- - -

Grp3 Grp2 Point 1:

-

Grp3 Grp2 Point 2:

-

Grp3 Grp2 Vector 2:

-

Grp3 Grp2 Point 3:

-

Grp3 Grp2 Vector 3:

-

Grp3 Grp2 Circle 3 center:

-

Grp3 Grp2 Line segment 3 point 1:

-

Grp3 Grp2 Line segment 3 point 2:

-

Grp3 Grp2 Point 4:

-

Grp3 Grp2 Point 5:

-

Grp3 Grp2 Circle 5 center:

-

Grp3 Grp2 Point 6:

-

Grp3 Grp2 Circle 6 center:

-

Grp3 Grp2 Line segment 6 point 1:

-

Grp3 Grp2 Line segment 6 point 2:

-

Grp3 Point 7:

-

Grp3 Circle 7 center:

-

Grp3 Line segment 7 point 1:

-

Grp3 Line segment 7 point 2:

-

Grp3 Vector 7 head:

-

Grp3 Vector 7 tail:

-
- -
- - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let P = [1, 2]; - let v = [4, 5]; - let vH = [4, 5]; - let c0 = [0, 0]; - - cy.get(cesc2("#/P1coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/P2coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/v2displacement") + " .mjx-mrow") - .eq(0) - .contains("(" + v + ")"); - cy.get(cesc2("#/P3coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/v3displacement") + " .mjx-mrow") - .eq(0) - .contains("(" + v + ")"); - cy.get(cesc2("#/c3center") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/l3point1") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/l3point2") + " .mjx-mrow") - .eq(0) - .contains("(" + vH + ")"); - cy.get(cesc2("#/P4coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/P5coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/c5center") + " .mjx-mrow") - .eq(0) - .contains("(" + c0 + ")"); - - cy.get(cesc2("#/grp2ps/P1coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp2ps/P2coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp2ps/v2displacement") + " .mjx-mrow") - .eq(0) - .contains("(" + v + ")"); - cy.get(cesc2("#/grp2ps/P3coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp2ps/v3displacement") + " .mjx-mrow") - .eq(0) - .contains("(" + v + ")"); - cy.get(cesc2("#/grp2ps/c3center") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp2ps/l3point1") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp2ps/l3point2") + " .mjx-mrow") - .eq(0) - .contains("(" + vH + ")"); - cy.get(cesc2("#/grp2ps/P4coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp2ps/P5coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp2ps/c5center") + " .mjx-mrow") - .eq(0) - .contains("(" + c0 + ")"); - cy.get(cesc2("#/grp2ps/P6coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp2ps/l6point1") + " .mjx-mrow") - .eq(0) - .contains("(" + c0 + ")"); - cy.get(cesc2("#/grp2ps/l6point2") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - - cy.get(cesc2("#/grp3ps/P1coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/P2coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/v2displacement") + " .mjx-mrow") - .eq(0) - .contains("(" + v + ")"); - cy.get(cesc2("#/grp3ps/P3coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/v3displacement") + " .mjx-mrow") - .eq(0) - .contains("(" + v + ")"); - cy.get(cesc2("#/grp3ps/c3center") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/l3point1") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/l3point2") + " .mjx-mrow") - .eq(0) - .contains("(" + vH + ")"); - cy.get(cesc2("#/grp3ps/P4coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/P5coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/c5center") + " .mjx-mrow") - .eq(0) - .contains("(" + c0 + ")"); - - cy.get(cesc2("#/grp3ps/grp2ps/P1coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/P2coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/v2displacement") + " .mjx-mrow") - .eq(0) - .contains("(" + v + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/P3coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/v3displacement") + " .mjx-mrow") - .eq(0) - .contains("(" + v + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/c3center") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/l3point1") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/l3point2") + " .mjx-mrow") - .eq(0) - .contains("(" + vH + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/P4coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/P5coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/c5center") + " .mjx-mrow") - .eq(0) - .contains("(" + c0 + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/P6coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/l6point1") + " .mjx-mrow") - .eq(0) - .contains("(" + c0 + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/l6point2") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/P7coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/l7point1") + " .mjx-mrow") - .eq(0) - .contains("(" + c0 + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/l7point2") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/v7head") + " .mjx-mrow") - .eq(0) - .contains("(" + vH + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/v7tail") + " .mjx-mrow") - .eq(0) - .contains("(" + c0 + ")"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g/P"].stateValues.xs).eqls(P); - expect(stateVariables["/g2/P"].stateValues.xs).eqls(P); - expect(stateVariables["/v"].stateValues.displacement).eqls(v); - expect(stateVariables["/g3/P"].stateValues.xs).eqls(P); - expect(stateVariables["/g3/v"].stateValues.displacement).eqls(v); - expect(stateVariables["/g3/c"].stateValues.center).eqls(P); - expect(stateVariables["/g3/l"].stateValues.endpoints[0]).eqls(P); - expect(stateVariables["/g3/l"].stateValues.endpoints[1]).eqls(vH); - expect(stateVariables["/g4/P"].stateValues.xs).eqls(P); - expect(stateVariables["/g5/P"].stateValues.xs).eqls(P); - expect(stateVariables["/g5/c"].stateValues.center).eqls(c0); - - expect(stateVariables["/grp2/g/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp2/g2/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp2/v"].stateValues.displacement).eqls(v); - expect(stateVariables["/grp2/g3/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp2/g3/v"].stateValues.displacement).eqls( - v, - ); - expect(stateVariables["/grp2/g3/c"].stateValues.center).eqls(P); - expect(stateVariables["/grp2/g3/l"].stateValues.endpoints[0]).eqls( - P, - ); - expect(stateVariables["/grp2/g3/l"].stateValues.endpoints[1]).eqls( - vH, - ); - expect(stateVariables["/grp2/g4/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp2/g5/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp2/g5/c"].stateValues.center).eqls(c0); - expect(stateVariables["/grp2/g6/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp2/g6/c"].stateValues.center).eqls(c0); - expect(stateVariables["/grp2/l"].stateValues.endpoints[0]).eqls(c0); - expect(stateVariables["/grp2/l"].stateValues.endpoints[1]).eqls(P); - - expect(stateVariables["/grp3/g/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp3/g2/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp3/v"].stateValues.displacement).eqls(v); - expect(stateVariables["/grp3/g3/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp3/g3/v"].stateValues.displacement).eqls( - v, - ); - expect(stateVariables["/grp3/g3/c"].stateValues.center).eqls(P); - expect(stateVariables["/grp3/g3/l"].stateValues.endpoints[0]).eqls( - P, - ); - expect(stateVariables["/grp3/g3/l"].stateValues.endpoints[1]).eqls( - vH, - ); - expect(stateVariables["/grp3/g4/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp3/g5/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp3/g5/c"].stateValues.center).eqls(c0); - - expect(stateVariables["/grp3/grp2/g/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp3/grp2/g2/P"].stateValues.xs).eqls(P); - expect( - stateVariables["/grp3/grp2/v"].stateValues.displacement, - ).eqls(v); - expect(stateVariables["/grp3/grp2/g3/P"].stateValues.xs).eqls(P); - expect( - stateVariables["/grp3/grp2/g3/v"].stateValues.displacement, - ).eqls(v); - expect(stateVariables["/grp3/grp2/g3/c"].stateValues.center).eqls( - P, - ); - expect( - stateVariables["/grp3/grp2/g3/l"].stateValues.endpoints[0], - ).eqls(P); - expect( - stateVariables["/grp3/grp2/g3/l"].stateValues.endpoints[1], - ).eqls(vH); - expect(stateVariables["/grp3/grp2/g4/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp3/grp2/g5/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp3/grp2/g5/c"].stateValues.center).eqls( - c0, - ); - expect(stateVariables["/grp3/grp2/g6/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp3/grp2/g6/c"].stateValues.center).eqls( - c0, - ); - expect( - stateVariables["/grp3/grp2/l"].stateValues.endpoints[0], - ).eqls(c0); - expect( - stateVariables["/grp3/grp2/l"].stateValues.endpoints[1], - ).eqls(P); - expect(stateVariables["/grp3/g7/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp3/g7/c"].stateValues.center).eqls(c0); - expect(stateVariables["/grp3/g7/l"].stateValues.endpoints[0]).eqls( - c0, - ); - expect(stateVariables["/grp3/g7/l"].stateValues.endpoints[1]).eqls( - P, - ); - expect(stateVariables["/grp3/g7/v"].stateValues.head).eqls(vH); - expect(stateVariables["/grp3/g7/v"].stateValues.tail).eqls(c0); - }); - - cy.log("move objects"); - cy.window().then(async (win) => { - P = [3, 5]; - win.callAction1({ - actionName: "movePoint", - componentName: "/g/P", - args: { x: P[0], y: P[1] }, - }); - v = [8, 7]; - vH = [5, 1]; - win.callAction1({ - actionName: "moveVector", - componentName: "/v", - args: { - headcoords: vH, - tailcoords: [vH[0] - v[0], vH[1] - v[1]], - }, - }); - c0 = [6, 0]; - win.callAction1({ - actionName: "moveCircle", - componentName: "/g5/c", - args: { center: c0 }, - }); - }); - - cy.get(cesc2("#/grp3ps/grp2ps/v7tail") + " .mjx-mrow").should( - "contain.text", - "(" + c0 + ")", - ); - - cy.get(cesc2("#/P1coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/P2coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/v2displacement") + " .mjx-mrow") - .eq(0) - .contains("(" + v + ")"); - cy.get(cesc2("#/P3coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/v3displacement") + " .mjx-mrow") - .eq(0) - .contains("(" + v + ")"); - cy.get(cesc2("#/c3center") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/l3point1") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/l3point2") + " .mjx-mrow") - .eq(0) - .contains("(" + vH + ")"); - cy.get(cesc2("#/P4coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/P5coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/c5center") + " .mjx-mrow") - .eq(0) - .contains("(" + c0 + ")"); - - cy.get(cesc2("#/grp2ps/P1coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp2ps/P2coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp2ps/v2displacement") + " .mjx-mrow") - .eq(0) - .contains("(" + v + ")"); - cy.get(cesc2("#/grp2ps/P3coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp2ps/v3displacement") + " .mjx-mrow") - .eq(0) - .contains("(" + v + ")"); - cy.get(cesc2("#/grp2ps/c3center") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp2ps/l3point1") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp2ps/l3point2") + " .mjx-mrow") - .eq(0) - .contains("(" + vH + ")"); - cy.get(cesc2("#/grp2ps/P4coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp2ps/P5coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp2ps/c5center") + " .mjx-mrow") - .eq(0) - .contains("(" + c0 + ")"); - cy.get(cesc2("#/grp2ps/P6coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp2ps/l6point1") + " .mjx-mrow") - .eq(0) - .contains("(" + c0 + ")"); - cy.get(cesc2("#/grp2ps/l6point2") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - - cy.get(cesc2("#/grp3ps/P1coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/P2coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/v2displacement") + " .mjx-mrow") - .eq(0) - .contains("(" + v + ")"); - cy.get(cesc2("#/grp3ps/P3coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/v3displacement") + " .mjx-mrow") - .eq(0) - .contains("(" + v + ")"); - cy.get(cesc2("#/grp3ps/c3center") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/l3point1") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/l3point2") + " .mjx-mrow") - .eq(0) - .contains("(" + vH + ")"); - cy.get(cesc2("#/grp3ps/P4coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/P5coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/c5center") + " .mjx-mrow") - .eq(0) - .contains("(" + c0 + ")"); - - cy.get(cesc2("#/grp3ps/grp2ps/P1coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/P2coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/v2displacement") + " .mjx-mrow") - .eq(0) - .contains("(" + v + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/P3coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/v3displacement") + " .mjx-mrow") - .eq(0) - .contains("(" + v + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/c3center") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/l3point1") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/l3point2") + " .mjx-mrow") - .eq(0) - .contains("(" + vH + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/P4coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/P5coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/c5center") + " .mjx-mrow") - .eq(0) - .contains("(" + c0 + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/P6coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/l6point1") + " .mjx-mrow") - .eq(0) - .contains("(" + c0 + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/l6point2") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/P7coords") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/l7point1") + " .mjx-mrow") - .eq(0) - .contains("(" + c0 + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/l7point2") + " .mjx-mrow") - .eq(0) - .contains("(" + P + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/v7head") + " .mjx-mrow") - .eq(0) - .contains("(" + vH + ")"); - cy.get(cesc2("#/grp3ps/grp2ps/v7tail") + " .mjx-mrow") - .eq(0) - .contains("(" + c0 + ")"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g/P"].stateValues.xs).eqls(P); - expect(stateVariables["/g2/P"].stateValues.xs).eqls(P); - expect(stateVariables["/v"].stateValues.displacement).eqls(v); - expect(stateVariables["/g3/P"].stateValues.xs).eqls(P); - expect(stateVariables["/g3/v"].stateValues.displacement).eqls(v); - expect(stateVariables["/g3/c"].stateValues.center).eqls(P); - expect(stateVariables["/g3/l"].stateValues.endpoints[0]).eqls(P); - expect(stateVariables["/g3/l"].stateValues.endpoints[1]).eqls(vH); - expect(stateVariables["/g4/P"].stateValues.xs).eqls(P); - expect(stateVariables["/g5/P"].stateValues.xs).eqls(P); - expect(stateVariables["/g5/c"].stateValues.center).eqls(c0); - - expect(stateVariables["/grp2/g/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp2/g2/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp2/v"].stateValues.displacement).eqls(v); - expect(stateVariables["/grp2/g3/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp2/g3/v"].stateValues.displacement).eqls( - v, - ); - expect(stateVariables["/grp2/g3/c"].stateValues.center).eqls(P); - expect(stateVariables["/grp2/g3/l"].stateValues.endpoints[0]).eqls( - P, - ); - expect(stateVariables["/grp2/g3/l"].stateValues.endpoints[1]).eqls( - vH, - ); - expect(stateVariables["/grp2/g4/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp2/g5/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp2/g5/c"].stateValues.center).eqls(c0); - expect(stateVariables["/grp2/g6/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp2/g6/c"].stateValues.center).eqls(c0); - expect(stateVariables["/grp2/l"].stateValues.endpoints[0]).eqls(c0); - expect(stateVariables["/grp2/l"].stateValues.endpoints[1]).eqls(P); - - expect(stateVariables["/grp3/g/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp3/g2/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp3/v"].stateValues.displacement).eqls(v); - expect(stateVariables["/grp3/g3/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp3/g3/v"].stateValues.displacement).eqls( - v, - ); - expect(stateVariables["/grp3/g3/c"].stateValues.center).eqls(P); - expect(stateVariables["/grp3/g3/l"].stateValues.endpoints[0]).eqls( - P, - ); - expect(stateVariables["/grp3/g3/l"].stateValues.endpoints[1]).eqls( - vH, - ); - expect(stateVariables["/grp3/g4/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp3/g5/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp3/g5/c"].stateValues.center).eqls(c0); - - expect(stateVariables["/grp3/grp2/g/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp3/grp2/g2/P"].stateValues.xs).eqls(P); - expect( - stateVariables["/grp3/grp2/v"].stateValues.displacement, - ).eqls(v); - expect(stateVariables["/grp3/grp2/g3/P"].stateValues.xs).eqls(P); - expect( - stateVariables["/grp3/grp2/g3/v"].stateValues.displacement, - ).eqls(v); - expect(stateVariables["/grp3/grp2/g3/c"].stateValues.center).eqls( - P, - ); - expect( - stateVariables["/grp3/grp2/g3/l"].stateValues.endpoints[0], - ).eqls(P); - expect( - stateVariables["/grp3/grp2/g3/l"].stateValues.endpoints[1], - ).eqls(vH); - expect(stateVariables["/grp3/grp2/g4/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp3/grp2/g5/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp3/grp2/g5/c"].stateValues.center).eqls( - c0, - ); - expect(stateVariables["/grp3/grp2/g6/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp3/grp2/g6/c"].stateValues.center).eqls( - c0, - ); - expect( - stateVariables["/grp3/grp2/l"].stateValues.endpoints[0], - ).eqls(c0); - expect( - stateVariables["/grp3/grp2/l"].stateValues.endpoints[1], - ).eqls(P); - expect(stateVariables["/grp3/g7/P"].stateValues.xs).eqls(P); - expect(stateVariables["/grp3/g7/c"].stateValues.center).eqls(c0); - expect(stateVariables["/grp3/g7/l"].stateValues.endpoints[0]).eqls( - c0, - ); - expect(stateVariables["/grp3/g7/l"].stateValues.endpoints[1]).eqls( - P, - ); - expect(stateVariables["/grp3/g7/v"].stateValues.head).eqls(vH); - expect(stateVariables["/grp3/g7/v"].stateValues.tail).eqls(c0); - }); - }); - - it("add children with copySource, recreated replacements include added children", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - - - - (3,4) - - - - - (5,6) - - - - - - (7,8) - - -

g2/P: $(g2/P)

-

g2/Q: $(g2/Q)

- - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/pP") + " .mjx-mrow") - .eq(0) - .should("have.text", "(5,6)"); - cy.get(cesc2("#/pQ") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,8)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g1"].activeChildren.length).eq(1); - expect(stateVariables["/g1"].activeChildren[0].componentName).eq( - "/g1/P", - ); - expect(stateVariables["/g1/P"].stateValues.xs).eqls([5, 6]); - expect(stateVariables["/g2"].activeChildren.length).eq(2); - expect(stateVariables["/g2"].activeChildren[0].componentName).eq( - "/g2/P", - ); - expect(stateVariables["/g2"].activeChildren[1].componentName).eq( - "/g2/Q", - ); - expect(stateVariables["/g2/P"].stateValues.xs).eqls([5, 6]); - expect(stateVariables["/g2/Q"].stateValues.xs).eqls([7, 8]); - }); - - cy.log("move points"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/g1/P", - args: { x: 10, y: 9 }, - }); - win.callAction1({ - actionName: "movePoint", - componentName: "/g2/Q", - args: { x: 8, y: 4 }, - }); - }); - - cy.get(cesc2("#/pQ") + " .mjx-mrow").should("contain.text", "(8,4)"); - cy.get(cesc2("#/pP") + " .mjx-mrow") - .eq(0) - .should("have.text", "(10,9)"); - cy.get(cesc2("#/pQ") + " .mjx-mrow") - .eq(0) - .should("have.text", "(8,4)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g1"].activeChildren.length).eq(1); - expect(stateVariables["/g1"].activeChildren[0].componentName).eq( - "/g1/P", - ); - expect(stateVariables["/g1/P"].stateValues.xs).eqls([10, 9]); - expect(stateVariables["/g2"].activeChildren.length).eq(2); - expect(stateVariables["/g2"].activeChildren[0].componentName).eq( - "/g2/P", - ); - expect(stateVariables["/g2"].activeChildren[1].componentName).eq( - "/g2/Q", - ); - expect(stateVariables["/g2/P"].stateValues.xs).eqls([10, 9]); - expect(stateVariables["/g2/Q"].stateValues.xs).eqls([8, 4]); - }); - - cy.log("switch to second option from conditional content"); - cy.get(cesc2("#/n") + " textarea").type("{end}2{enter}", { - force: true, - }); - - cy.get(cesc2("#/pP") + " .mjx-mrow").should("contain.text", "(3,4)"); - cy.get(cesc2("#/pP") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,4)"); - cy.get(cesc2("#/pQ") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,8)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g1"].activeChildren.length).eq(1); - expect(stateVariables["/g1"].activeChildren[0].componentName).eq( - "/g1/P", - ); - expect(stateVariables["/g1/P"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/g2"].activeChildren.length).eq(2); - expect(stateVariables["/g2"].activeChildren[0].componentName).eq( - "/g2/P", - ); - expect(stateVariables["/g2"].activeChildren[1].componentName).eq( - "/g2/Q", - ); - expect(stateVariables["/g2/P"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/g2/Q"].stateValues.xs).eqls([7, 8]); - }); - - cy.log("move new points"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "movePoint", - componentName: "/g1/P", - args: { x: 6, y: 1 }, - }); - win.callAction1({ - actionName: "movePoint", - componentName: "/g2/Q", - args: { x: 9, y: 3 }, - }); - }); - - cy.get(cesc2("#/pQ") + " .mjx-mrow").should("contain.text", "(9,3)"); - cy.get(cesc2("#/pP") + " .mjx-mrow") - .eq(0) - .should("have.text", "(6,1)"); - cy.get(cesc2("#/pQ") + " .mjx-mrow") - .eq(0) - .should("have.text", "(9,3)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g1"].activeChildren.length).eq(1); - expect(stateVariables["/g1"].activeChildren[0].componentName).eq( - "/g1/P", - ); - expect(stateVariables["/g1/P"].stateValues.xs).eqls([6, 1]); - expect(stateVariables["/g2"].activeChildren.length).eq(2); - expect(stateVariables["/g2"].activeChildren[0].componentName).eq( - "/g2/P", - ); - expect(stateVariables["/g2"].activeChildren[1].componentName).eq( - "/g2/Q", - ); - expect(stateVariables["/g2/P"].stateValues.xs).eqls([6, 1]); - expect(stateVariables["/g2/Q"].stateValues.xs).eqls([9, 3]); - }); - - cy.log("switch back to first option from conditional content"); - cy.get(cesc2("#/n") + " textarea").type( - "{end}{backspace}{backspace}0{enter}", - { force: true }, - ); - - cy.get(cesc2("#/pP") + " .mjx-mrow").should("contain.text", "(5,6)"); - cy.get(cesc2("#/pP") + " .mjx-mrow") - .eq(0) - .should("have.text", "(5,6)"); - cy.get(cesc2("#/pQ") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,8)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g1"].activeChildren.length).eq(1); - expect(stateVariables["/g1"].activeChildren[0].componentName).eq( - "/g1/P", - ); - expect(stateVariables["/g1/P"].stateValues.xs).eqls([5, 6]); - expect(stateVariables["/g2"].activeChildren.length).eq(2); - expect(stateVariables["/g2"].activeChildren[0].componentName).eq( - "/g2/P", - ); - expect(stateVariables["/g2"].activeChildren[1].componentName).eq( - "/g2/Q", - ); - expect(stateVariables["/g2/P"].stateValues.xs).eqls([5, 6]); - expect(stateVariables["/g2/Q"].stateValues.xs).eqls([7, 8]); - }); - }); - - it("assign names with copySource of group and map", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - 12 - - - - - - - apple - banana - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/a")).should("have.text", "hi 1"); - cy.get(cesc2("#/b")).should("have.text", "hi 2"); - cy.get(cesc2("#/c")).should("have.text", "hi 1"); - cy.get(cesc2("#/d")).should("have.text", "hi 2"); - cy.get(cesc2("#/e")).should("have.text", "apple"); - cy.get(cesc2("#/f")).should("have.text", "banana"); - cy.get(cesc2("#/g")).should("have.text", "apple"); - cy.get(cesc2("#/h")).should("have.text", "banana"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eq("hi 1"); - expect(stateVariables["/b"].stateValues.value).eq("hi 2"); - expect(stateVariables["/c"].stateValues.value).eq("hi 1"); - expect(stateVariables["/d"].stateValues.value).eq("hi 2"); - expect(stateVariables["/e"].stateValues.value).eq("apple"); - expect(stateVariables["/f"].stateValues.value).eq("banana"); - expect(stateVariables["/g"].stateValues.value).eq("apple"); - expect(stateVariables["/h"].stateValues.value).eq("banana"); - }); - }); - - it("assign names with macro copy of group and map", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - 12 - - - $map1{name="map2" assignNames="(c) (d)"} - - - - apple - banana - - - $grp1{name="grp2" assignNames="g h"} - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/a")).should("have.text", "hi 1"); - cy.get(cesc2("#/b")).should("have.text", "hi 2"); - cy.get(cesc2("#/c")).should("have.text", "hi 1"); - cy.get(cesc2("#/d")).should("have.text", "hi 2"); - cy.get(cesc2("#/e")).should("have.text", "apple"); - cy.get(cesc2("#/f")).should("have.text", "banana"); - cy.get(cesc2("#/g")).should("have.text", "apple"); - cy.get(cesc2("#/h")).should("have.text", "banana"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eq("hi 1"); - expect(stateVariables["/b"].stateValues.value).eq("hi 2"); - expect(stateVariables["/c"].stateValues.value).eq("hi 1"); - expect(stateVariables["/d"].stateValues.value).eq("hi 2"); - expect(stateVariables["/e"].stateValues.value).eq("apple"); - expect(stateVariables["/f"].stateValues.value).eq("banana"); - expect(stateVariables["/g"].stateValues.value).eq("apple"); - expect(stateVariables["/h"].stateValues.value).eq("banana"); - }); - }); - - it("assign names with copySource of group and map, newNamespace", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - 12 - - - - - - - apple - banana - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/map1/a/t")).should("have.text", "hi 1"); - cy.get(cesc2("#/map1/b/t")).should("have.text", "hi 2"); - cy.get(cesc2("#/map2/c/t")).should("have.text", "hi 1"); - cy.get(cesc2("#/map2/d/t")).should("have.text", "hi 2"); - cy.get(cesc2("#/grp1/a")).should("have.text", "apple"); - cy.get(cesc2("#/grp1/b")).should("have.text", "banana"); - cy.get(cesc2("#/grp2/c")).should("have.text", "apple"); - cy.get(cesc2("#/grp2/d")).should("have.text", "banana"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/map1/a/t"].stateValues.value).eq("hi 1"); - expect(stateVariables["/map1/b/t"].stateValues.value).eq("hi 2"); - expect(stateVariables["/map2/c/t"].stateValues.value).eq("hi 1"); - expect(stateVariables["/map2/d/t"].stateValues.value).eq("hi 2"); - expect(stateVariables["/grp1/a"].stateValues.value).eq("apple"); - expect(stateVariables["/grp1/b"].stateValues.value).eq("banana"); - expect(stateVariables["/grp2/c"].stateValues.value).eq("apple"); - expect(stateVariables["/grp2/d"].stateValues.value).eq("banana"); - }); - }); - - it("assign names with macro copy of group and map, newNamespace", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - 12 - - - $map1{name="map2" assignNames="c d"} - - - - apple - banana - - - $grp1{name="grp2" assignNames="c d"} - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/map1/a/t")).should("have.text", "hi 1"); - cy.get(cesc2("#/map1/b/t")).should("have.text", "hi 2"); - cy.get(cesc2("#/map2/c/t")).should("have.text", "hi 1"); - cy.get(cesc2("#/map2/d/t")).should("have.text", "hi 2"); - cy.get(cesc2("#/grp1/a")).should("have.text", "apple"); - cy.get(cesc2("#/grp1/b")).should("have.text", "banana"); - cy.get(cesc2("#/grp2/c")).should("have.text", "apple"); - cy.get(cesc2("#/grp2/d")).should("have.text", "banana"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/map1/a/t"].stateValues.value).eq("hi 1"); - expect(stateVariables["/map1/b/t"].stateValues.value).eq("hi 2"); - expect(stateVariables["/map2/c/t"].stateValues.value).eq("hi 1"); - expect(stateVariables["/map2/d/t"].stateValues.value).eq("hi 2"); - expect(stateVariables["/grp1/a"].stateValues.value).eq("apple"); - expect(stateVariables["/grp1/b"].stateValues.value).eq("banana"); - expect(stateVariables["/grp2/c"].stateValues.value).eq("apple"); - expect(stateVariables["/grp2/d"].stateValues.value).eq("banana"); - }); - }); - - it("copySource composite replacement implicitly skips assignNames", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - hi - bye - - - - - - -

- -

- -

- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/a")).should("have.text", "hi"); - cy.get(cesc2("#/b")).should("have.text", "bye"); - cy.get(cesc2("#/c")).should("have.text", "hi"); - cy.get(cesc2("#/d")).should("have.text", "bye"); - cy.get(cesc2("#/_p2/c")).should("have.text", "hi"); - cy.get(cesc2("#/_p2/d")).should("have.text", "bye"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eq("hi"); - expect(stateVariables["/b"].stateValues.value).eq("bye"); - expect(stateVariables["/c"].stateValues.value).eq("hi"); - expect(stateVariables["/d"].stateValues.value).eq("bye"); - expect(stateVariables["/_p2/c"].stateValues.value).eq("hi"); - expect(stateVariables["/_p2/d"].stateValues.value).eq("bye"); - }); - }); - - it("macro copy composite replacement implicitly skips assignNames", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - hi - bye - - - $t1 - $t2 - - -

- $_group1{assignNames="c d"} -

- - $_p1{name="p2" newNamespace} - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/a")).should("have.text", "hi"); - cy.get(cesc2("#/b")).should("have.text", "bye"); - cy.get(cesc2("#/c")).should("have.text", "hi"); - cy.get(cesc2("#/d")).should("have.text", "bye"); - cy.get(cesc2("#/p2/c")).should("have.text", "hi"); - cy.get(cesc2("#/p2/d")).should("have.text", "bye"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/a"].stateValues.value).eq("hi"); - expect(stateVariables["/b"].stateValues.value).eq("bye"); - expect(stateVariables["/c"].stateValues.value).eq("hi"); - expect(stateVariables["/d"].stateValues.value).eq("bye"); - expect(stateVariables["/p2/c"].stateValues.value).eq("hi"); - expect(stateVariables["/p2/d"].stateValues.value).eq("bye"); - }); - }); - - it("copy and macro's prescribed name is used to assign name to replacement", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - hi - - $t1{name="t3"} - - - apple - banana - - - $grp1{name="grp3"} - - (3,4) - - - $p.x{assignNames="x3"} - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/t1")).should("have.text", "hi"); - cy.get(cesc2("#/t2")).should("have.text", "hi"); - cy.get(cesc2("#/t3")).should("have.text", "hi"); - - cy.get(cesc2("#/grp1/_text1")).should("have.text", "apple"); - cy.get(cesc2("#/grp1/_text2")).should("have.text", "banana"); - cy.get(cesc2("#/grp2/_text1")).should("have.text", "apple"); - cy.get(cesc2("#/grp2/_text2")).should("have.text", "banana"); - cy.get(cesc2("#/grp3/_text1")).should("have.text", "apple"); - cy.get(cesc2("#/grp3/_text2")).should("have.text", "banana"); - - cy.get(cesc2("#/p") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,4)"); - cy.get(cesc2("#/x1") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc2("#/x2") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc2("#/x3") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/t1"].stateValues.value).eq("hi"); - expect(stateVariables["/t2"].stateValues.value).eq("hi"); - expect(stateVariables["/t3"].stateValues.value).eq("hi"); - - expect(stateVariables["/grp1/_text1"].stateValues.value).eq( - "apple", - ); - expect(stateVariables["/grp1/_text2"].stateValues.value).eq( - "banana", - ); - expect(stateVariables["/grp2/_text1"].stateValues.value).eq( - "apple", - ); - expect(stateVariables["/grp2/_text2"].stateValues.value).eq( - "banana", - ); - expect(stateVariables["/grp3/_text1"].stateValues.value).eq( - "apple", - ); - expect(stateVariables["/grp3/_text2"].stateValues.value).eq( - "banana", - ); - - expect(stateVariables["/p"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/x1"].stateValues.value).eq(3); - expect(stateVariables["/x2"].stateValues.value).eq(3); - expect(stateVariables["/x3"].stateValues.value).eq(3); - }); - }); - - it("copy's automatically generated name not used", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - hi $t1 - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/t1")).should("have.text", "hi"); - cy.get(cesc2("#/_document1")).should("contain.text", "hi hi"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/t1"].stateValues.value).eq("hi"); - expect(stateVariables["/_copy1"]).eq(undefined); - - let secondTextComponentName = - stateVariables["/_document1"].activeChildren[2].componentName; - expect( - stateVariables[secondTextComponentName].stateValues.value, - ).eq("hi"); - - cy.get(cesc2("#" + secondTextComponentName)).should( - "have.text", - "hi", - ); - }); - }); - - it("copy and macro's ssignNames is used to assign name to prop replacement", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - (3,4) - - $p.x{assignNames="x2"} - - - $p.coords{assignNames="c2"} - - - $p.xs{assignNames="x12 x22"} - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/p") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,4)"); - - cy.get(cesc2("#/x1") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc2("#/x2") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - - cy.get(cesc2("#/c1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,4)"); - cy.get(cesc2("#/c2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,4)"); - - cy.get(cesc2("#/x11") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc2("#/x21") + " .mjx-mrow") - .eq(0) - .should("have.text", "4"); - cy.get(cesc2("#/x12") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc2("#/x22") + " .mjx-mrow") - .eq(0) - .should("have.text", "4"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p"].stateValues.xs).eqls([3, 4]); - expect(stateVariables["/x1"].stateValues.value).eq(3); - expect(stateVariables["/x2"].stateValues.value).eq(3); - expect(stateVariables["/c1"].stateValues.value).eqls([ - "vector", - 3, - 4, - ]); - expect(stateVariables["/c2"].stateValues.value).eqls([ - "vector", - 3, - 4, - ]); - expect(stateVariables["/x11"].stateValues.value).eq(3); - expect(stateVariables["/x21"].stateValues.value).eq(4); - expect(stateVariables["/x12"].stateValues.value).eq(3); - expect(stateVariables["/x22"].stateValues.value).eq(4); - }); - }); - - it("add children to copySource with prop and propIndex", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - - - - - - - -

P:

-

label of P:

- - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/Pa") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc2("#/l") + " .mjx-mrow") - .eq(0) - .should("have.text", "V1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.xs).eqls([1, 2]); - expect(stateVariables["/P"].stateValues.label).eq("\\(V_ 1\\)"); - }); - - cy.log("change to vertex 2"); - cy.get(cesc2("#/ind") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - cy.get(cesc2("#/Pa") + " .mjx-mrow").should("contain.text", "(5,2)"); - cy.get(cesc2("#/Pa") + " .mjx-mrow") - .eq(0) - .should("have.text", "(5,2)"); - cy.get(cesc2("#/l") + " .mjx-mrow") - .eq(0) - .should("have.text", "V2"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.xs).eqls([5, 2]); - expect(stateVariables["/P"].stateValues.label).eq("\\(V_ 2\\)"); - }); - - cy.log("invalid vertex"); - cy.get(cesc2("#/ind") + " textarea").type("{end}{backspace}{enter}", { - force: true, - }); - cy.get(cesc2("#/Pa") + " .mjx-mrow").should("contain.text", "(0,0)"); - cy.get(cesc2("#/Pa") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,0)"); - cy.get(cesc2("#/l")).should("have.text", ""); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.xs).eqls([0, 0]); - expect(stateVariables["/P"].stateValues.label).eq(""); - }); - - cy.log("change to vertex 3"); - cy.get(cesc2("#/ind") + " textarea").type("3{enter}", { - force: true, - }); - cy.get(cesc2("#/Pa") + " .mjx-mrow").should("contain.text", "(5,8)"); - cy.get(cesc2("#/Pa") + " .mjx-mrow") - .eq(0) - .should("have.text", "(5,8)"); - cy.get(cesc2("#/l") + " .mjx-mrow") - .eq(0) - .should("have.text", "V3"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/P"].stateValues.xs).eqls([5, 8]); - expect(stateVariables["/P"].stateValues.label).eq("\\(V_ 3\\)"); - }); - }); - - it("dot and array notation", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (2,3) - - -

P: $P

-

P: $P[1]

-

nothing: $P[2]

-

P.: $P.

-

P.1: $P.1

-

x of P: $P.x

-

y of P: $P.y

-

nothing: $P._x

-

x of P: $P.xs[1]

-

y of P: $P.xs[2]

-

nothing: $P.xs[3]

- - -

P: $(P)

-

(P).x: $(P).x

-

no match: $(P.)

-

nothing: $(P.1)

-

x of P: $(P.x)

-

y of P: $(P.y)

-

x of P: $(P.xs[1])

-

y of P: $(P.xs[2])

- - -

P: $P

-

P:

-

nothing:

-

nothing:

-

nothing:

-

x of P:

-

y of P:

-

nothing:

-

x of P:

-

y of P:

-

nothing:

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2,3)"); - cy.get(cesc2("#/p2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2,3)"); - cy.get(cesc2("#/p3")).should("have.text", "nothing: "); - cy.get(cesc2("#/p4") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2,3)"); - cy.get(cesc2("#/p4")).should("contain.text", ")."); - cy.get(cesc2("#/p5") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2,3)"); - cy.get(cesc2("#/p5")).should("contain.text", ").1"); - cy.get(cesc2("#/p6") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc2("#/p7") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc2("#/p8")).should("have.text", "nothing: "); - cy.get(cesc2("#/p9") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc2("#/p10") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc2("#/p11")).should("have.text", "nothing: "); - - cy.get(cesc2("#/p12") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2,3)"); - cy.get(cesc2("#/p13") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2,3)"); - cy.get(cesc2("#/p13")).should("contain.text", ").x"); - cy.get(cesc2("#/p14")).should("have.text", "no match: $(P.)"); - cy.get(cesc2("#/p15")).should("have.text", "nothing: "); - cy.get(cesc2("#/p16") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc2("#/p17") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc2("#/p18") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc2("#/p19") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - - cy.get(cesc2("#/p20") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2,3)"); - cy.get(cesc2("#/p21") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2,3)"); - cy.get(cesc2("#/p22")).should("have.text", "nothing: "); - cy.get(cesc2("#/p23")).should("have.text", "nothing: "); - cy.get(cesc2("#/p24")).should("have.text", "nothing: "); - cy.get(cesc2("#/p25") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc2("#/p26") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc2("#/p27")).should("have.text", "nothing: "); - cy.get(cesc2("#/p28") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc2("#/p29") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc2("#/p30")).should("have.text", "nothing: "); - }); - - it("dot and array notation, chaining, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - -

$l.points.coords

-

$l.points.x

-

$l.points.y

-

$l.points.bad

-

$l.points.xs[1]

-

$l.points.xs[2]

-

$l.points.xs[3]

- -

$l.points[1].coords

-

$l.points[1].x

-

$l.points[1].y

-

$l.points[1].bad

-

$l.points[1].xs[1]

-

$l.points[1].xs[2]

-

$l.points[1].xs[3]

- -

$l.points[2].coords

-

$l.points[2].x

-

$l.points[2].y

-

$l.points[2].bad

-

$l.points[2].xs[1]

-

$l.points[2].xs[2]

-

$l.points[2].xs[3]

- -

$l.points[3].coords

-

$l.points[3].x

-

$l.points[3].y

-

$l.points[3].bad

-

$l.points[3].xs[1]

-

$l.points[3].xs[2]

-

$l.points[3].xs[3]

- -

$l.points.coords.latex

-

$l.points.x.latex

-

$l.points.y.latex

-

$l.points.bad.latex

-

$l.points.xs[1].latex

-

$l.points.xs[2].latex

-

$l.points.xs[3].latex

- -

$l.points[1].coords.latex

-

$l.points[1].x.latex

-

$l.points[1].y.latex

-

$l.points[1].bad.latex

-

$l.points[1].xs[1].latex

-

$l.points[1].xs[2].latex

-

$l.points[1].xs[3].latex

- -

$l.points[1][1]

-

$l.points[1][2]

-

$l.points[2][1]

-

$l.points[2][2]

-

$l.points[0][1]

-

$l.points[1][0]

-

$l.points[1][3]

-

$l.points[3][1]

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(23,3)"); - cy.get(cesc2("#/p1") + " .mjx-mrow") - .eq(3) - .should("have.text", "(5,6)"); - cy.get(cesc2("#/p2") + " .mjx-mrow") - .eq(0) - .should("have.text", "23"); - cy.get(cesc2("#/p2") + " .mjx-mrow") - .eq(1) - .should("have.text", "5"); - cy.get(cesc2("#/p3") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc2("#/p3") + " .mjx-mrow") - .eq(1) - .should("have.text", "6"); - cy.get(cesc2("#/p4")).should("have.text", ""); - cy.get(cesc2("#/p5") + " .mjx-mrow") - .eq(0) - .should("have.text", "23"); - cy.get(cesc2("#/p5") + " .mjx-mrow") - .eq(1) - .should("have.text", "5"); - cy.get(cesc2("#/p6") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc2("#/p6") + " .mjx-mrow") - .eq(1) - .should("have.text", "6"); - cy.get(cesc2("#/p7")).should("have.text", ""); - - cy.get(cesc2("#/p8") + " .mjx-mrow") - .eq(0) - .should("have.text", "(23,3)"); - cy.get(cesc2("#/p8") + " .mjx-mrow") - .eq(3) - .should("not.exist"); - cy.get(cesc2("#/p9") + " .mjx-mrow") - .eq(0) - .should("have.text", "23"); - cy.get(cesc2("#/p9") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p10") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc2("#/p10") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p11")).should("have.text", ""); - cy.get(cesc2("#/p12") + " .mjx-mrow") - .eq(0) - .should("have.text", "23"); - cy.get(cesc2("#/p12") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p13") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc2("#/p13") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p14")).should("have.text", ""); - - cy.get(cesc2("#/p15") + " .mjx-mrow") - .eq(0) - .should("have.text", "(5,6)"); - cy.get(cesc2("#/p15") + " .mjx-mrow") - .eq(3) - .should("not.exist"); - cy.get(cesc2("#/p16") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - cy.get(cesc2("#/p16") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p17") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc2("#/p17") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p18")).should("have.text", ""); - cy.get(cesc2("#/p19") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - cy.get(cesc2("#/p19") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p20") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc2("#/p20") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p21")).should("have.text", ""); - - cy.get(cesc2("#/p22")).should("have.text", ""); - cy.get(cesc2("#/p23")).should("have.text", ""); - cy.get(cesc2("#/p24")).should("have.text", ""); - cy.get(cesc2("#/p25")).should("have.text", ""); - cy.get(cesc2("#/p26")).should("have.text", ""); - cy.get(cesc2("#/p27")).should("have.text", ""); - cy.get(cesc2("#/p28")).should("have.text", ""); - - cy.get(cesc2("#/p29")).should( - "have.text", - "\\left( \\frac{2}{3}, 3 \\right), \\left( 5, 6 \\right)", - ); - cy.get(cesc2("#/p30")).should("have.text", "\\frac{2}{3}, 5"); - cy.get(cesc2("#/p31")).should("have.text", "3, 6"); - cy.get(cesc2("#/p32")).should("have.text", ""); - cy.get(cesc2("#/p33")).should("have.text", "\\frac{2}{3}, 5"); - cy.get(cesc2("#/p34")).should("have.text", "3, 6"); - cy.get(cesc2("#/p35")).should("have.text", ""); - - cy.get(cesc2("#/p36")).should( - "have.text", - "\\left( \\frac{2}{3}, 3 \\right)", - ); - cy.get(cesc2("#/p37")).should("have.text", "\\frac{2}{3}"); - cy.get(cesc2("#/p38")).should("have.text", "3"); - cy.get(cesc2("#/p39")).should("have.text", ""); - cy.get(cesc2("#/p40")).should("have.text", "\\frac{2}{3}"); - cy.get(cesc2("#/p41")).should("have.text", "3"); - cy.get(cesc2("#/p42")).should("have.text", ""); - - cy.get(cesc2("#/p43") + " .mjx-mrow") - .eq(0) - .should("have.text", "23"); - cy.get(cesc2("#/p44") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc2("#/p45") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - cy.get(cesc2("#/p46") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc2("#/p47")).should("have.text", ""); - cy.get(cesc2("#/p48")).should("have.text", ""); - cy.get(cesc2("#/p49")).should("have.text", ""); - cy.get(cesc2("#/p50")).should("have.text", ""); - - cy.log("move points"); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveLine", - componentName: "/l", - args: { - point1coords: [7, 8], - point2coords: [9, 0], - }, - }); - }); - - cy.get(cesc2("#/p29")).should( - "have.text", - "\\left( 7, 8 \\right), \\left( 9, 0 \\right)", - ); - - cy.get(cesc2("#/p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,8)"); - cy.get(cesc2("#/p1") + " .mjx-mrow") - .eq(3) - .should("have.text", "(9,0)"); - cy.get(cesc2("#/p2") + " .mjx-mrow") - .eq(0) - .should("have.text", "7"); - cy.get(cesc2("#/p2") + " .mjx-mrow") - .eq(1) - .should("have.text", "9"); - cy.get(cesc2("#/p3") + " .mjx-mrow") - .eq(0) - .should("have.text", "8"); - cy.get(cesc2("#/p3") + " .mjx-mrow") - .eq(1) - .should("have.text", "0"); - cy.get(cesc2("#/p4")).should("have.text", ""); - cy.get(cesc2("#/p5") + " .mjx-mrow") - .eq(0) - .should("have.text", "7"); - cy.get(cesc2("#/p5") + " .mjx-mrow") - .eq(1) - .should("have.text", "9"); - cy.get(cesc2("#/p6") + " .mjx-mrow") - .eq(0) - .should("have.text", "8"); - cy.get(cesc2("#/p6") + " .mjx-mrow") - .eq(1) - .should("have.text", "0"); - cy.get(cesc2("#/p7")).should("have.text", ""); - - cy.get(cesc2("#/p8") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,8)"); - cy.get(cesc2("#/p8") + " .mjx-mrow") - .eq(3) - .should("not.exist"); - cy.get(cesc2("#/p9") + " .mjx-mrow") - .eq(0) - .should("have.text", "7"); - cy.get(cesc2("#/p9") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p10") + " .mjx-mrow") - .eq(0) - .should("have.text", "8"); - cy.get(cesc2("#/p10") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p11")).should("have.text", ""); - cy.get(cesc2("#/p12") + " .mjx-mrow") - .eq(0) - .should("have.text", "7"); - cy.get(cesc2("#/p12") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p13") + " .mjx-mrow") - .eq(0) - .should("have.text", "8"); - cy.get(cesc2("#/p13") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p14")).should("have.text", ""); - - cy.get(cesc2("#/p15") + " .mjx-mrow") - .eq(0) - .should("have.text", "(9,0)"); - cy.get(cesc2("#/p15") + " .mjx-mrow") - .eq(3) - .should("not.exist"); - cy.get(cesc2("#/p16") + " .mjx-mrow") - .eq(0) - .should("have.text", "9"); - cy.get(cesc2("#/p16") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p17") + " .mjx-mrow") - .eq(0) - .should("have.text", "0"); - cy.get(cesc2("#/p17") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p18")).should("have.text", ""); - cy.get(cesc2("#/p19") + " .mjx-mrow") - .eq(0) - .should("have.text", "9"); - cy.get(cesc2("#/p19") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p20") + " .mjx-mrow") - .eq(0) - .should("have.text", "0"); - cy.get(cesc2("#/p20") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p21")).should("have.text", ""); - - cy.get(cesc2("#/p22")).should("have.text", ""); - cy.get(cesc2("#/p23")).should("have.text", ""); - cy.get(cesc2("#/p24")).should("have.text", ""); - cy.get(cesc2("#/p25")).should("have.text", ""); - cy.get(cesc2("#/p26")).should("have.text", ""); - cy.get(cesc2("#/p27")).should("have.text", ""); - cy.get(cesc2("#/p28")).should("have.text", ""); - - cy.get(cesc2("#/p29")).should( - "have.text", - "\\left( 7, 8 \\right), \\left( 9, 0 \\right)", - ); - cy.get(cesc2("#/p30")).should("have.text", "7, 9"); - cy.get(cesc2("#/p31")).should("have.text", "8, 0"); - cy.get(cesc2("#/p32")).should("have.text", ""); - cy.get(cesc2("#/p33")).should("have.text", "7, 9"); - cy.get(cesc2("#/p34")).should("have.text", "8, 0"); - cy.get(cesc2("#/p35")).should("have.text", ""); - - cy.get(cesc2("#/p36")).should("have.text", "\\left( 7, 8 \\right)"); - cy.get(cesc2("#/p37")).should("have.text", "7"); - cy.get(cesc2("#/p38")).should("have.text", "8"); - cy.get(cesc2("#/p39")).should("have.text", ""); - cy.get(cesc2("#/p40")).should("have.text", "7"); - cy.get(cesc2("#/p41")).should("have.text", "8"); - cy.get(cesc2("#/p42")).should("have.text", ""); - - cy.get(cesc2("#/p43") + " .mjx-mrow") - .eq(0) - .should("have.text", "7"); - cy.get(cesc2("#/p44") + " .mjx-mrow") - .eq(0) - .should("have.text", "8"); - cy.get(cesc2("#/p45") + " .mjx-mrow") - .eq(0) - .should("have.text", "9"); - cy.get(cesc2("#/p46") + " .mjx-mrow") - .eq(0) - .should("have.text", "0"); - cy.get(cesc2("#/p47")).should("have.text", ""); - cy.get(cesc2("#/p48")).should("have.text", ""); - cy.get(cesc2("#/p49")).should("have.text", ""); - cy.get(cesc2("#/p50")).should("have.text", ""); - }); - - it("dot and array notation, chaining, copies", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - -

-

-

-

-

-

-

- -

-

-

-

-

-

-

- -

-

-

-

-

-

-

- -

-

-

-

-

-

-

- -

-

-

-

-

-

-

- -

-

-

-

-

-

-

- -

-

-

-

-

-

-

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(23,3)"); - cy.get(cesc2("#/p1") + " .mjx-mrow") - .eq(3) - .should("have.text", "(5,6)"); - cy.get(cesc2("#/p2") + " .mjx-mrow") - .eq(0) - .should("have.text", "23"); - cy.get(cesc2("#/p2") + " .mjx-mrow") - .eq(1) - .should("have.text", "5"); - cy.get(cesc2("#/p3") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc2("#/p3") + " .mjx-mrow") - .eq(1) - .should("have.text", "6"); - cy.get(cesc2("#/p4")).should("have.text", ""); - cy.get(cesc2("#/p5") + " .mjx-mrow") - .eq(0) - .should("have.text", "23"); - cy.get(cesc2("#/p5") + " .mjx-mrow") - .eq(1) - .should("have.text", "5"); - cy.get(cesc2("#/p6") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc2("#/p6") + " .mjx-mrow") - .eq(1) - .should("have.text", "6"); - cy.get(cesc2("#/p7")).should("have.text", ""); - - cy.get(cesc2("#/p8") + " .mjx-mrow") - .eq(0) - .should("have.text", "(23,3)"); - cy.get(cesc2("#/p8") + " .mjx-mrow") - .eq(3) - .should("not.exist"); - cy.get(cesc2("#/p9") + " .mjx-mrow") - .eq(0) - .should("have.text", "23"); - cy.get(cesc2("#/p9") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p10") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc2("#/p10") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p11")).should("have.text", ""); - cy.get(cesc2("#/p12") + " .mjx-mrow") - .eq(0) - .should("have.text", "23"); - cy.get(cesc2("#/p12") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p13") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc2("#/p13") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p14")).should("have.text", ""); - - cy.get(cesc2("#/p15") + " .mjx-mrow") - .eq(0) - .should("have.text", "(5,6)"); - cy.get(cesc2("#/p15") + " .mjx-mrow") - .eq(3) - .should("not.exist"); - cy.get(cesc2("#/p16") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - cy.get(cesc2("#/p16") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p17") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc2("#/p17") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p18")).should("have.text", ""); - cy.get(cesc2("#/p19") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - cy.get(cesc2("#/p19") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p20") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc2("#/p20") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p21")).should("have.text", ""); - - cy.get(cesc2("#/p22")).should("have.text", ""); - cy.get(cesc2("#/p23")).should("have.text", ""); - cy.get(cesc2("#/p24")).should("have.text", ""); - cy.get(cesc2("#/p25")).should("have.text", ""); - cy.get(cesc2("#/p26")).should("have.text", ""); - cy.get(cesc2("#/p27")).should("have.text", ""); - cy.get(cesc2("#/p28")).should("have.text", ""); - - cy.get(cesc2("#/p29")).should( - "have.text", - "\\left( \\frac{2}{3}, 3 \\right), \\left( 5, 6 \\right)", - ); - cy.get(cesc2("#/p30")).should("have.text", "\\frac{2}{3}, 5"); - cy.get(cesc2("#/p31")).should("have.text", "3, 6"); - cy.get(cesc2("#/p32")).should("have.text", ""); - cy.get(cesc2("#/p33")).should("have.text", "\\frac{2}{3}, 5"); - cy.get(cesc2("#/p34")).should("have.text", "3, 6"); - cy.get(cesc2("#/p35")).should("have.text", ""); - - cy.get(cesc2("#/p36")).should( - "have.text", - "\\left( \\frac{2}{3}, 3 \\right)", - ); - cy.get(cesc2("#/p37")).should("have.text", "\\frac{2}{3}"); - cy.get(cesc2("#/p38")).should("have.text", "3"); - cy.get(cesc2("#/p39")).should("have.text", ""); - cy.get(cesc2("#/p40")).should("have.text", "\\frac{2}{3}"); - cy.get(cesc2("#/p41")).should("have.text", "3"); - cy.get(cesc2("#/p42")).should("have.text", ""); - - cy.get(cesc2("#/p43") + " .mjx-mrow") - .eq(0) - .should("have.text", "23"); - cy.get(cesc2("#/p44") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc2("#/p45") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - cy.get(cesc2("#/p46") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc2("#/p47")).should("have.text", ""); - cy.get(cesc2("#/p48")).should("have.text", ""); - cy.get(cesc2("#/p49")).should("have.text", ""); - cy.get(cesc2("#/p50")).should("have.text", ""); - - cy.log("move points"); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveLine", - componentName: "/l", - args: { - point1coords: [7, 8], - point2coords: [9, 0], - }, - }); - }); - - cy.get(cesc2("#/p29")).should( - "have.text", - "\\left( 7, 8 \\right), \\left( 9, 0 \\right)", - ); - - cy.get(cesc2("#/p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,8)"); - cy.get(cesc2("#/p1") + " .mjx-mrow") - .eq(3) - .should("have.text", "(9,0)"); - cy.get(cesc2("#/p2") + " .mjx-mrow") - .eq(0) - .should("have.text", "7"); - cy.get(cesc2("#/p2") + " .mjx-mrow") - .eq(1) - .should("have.text", "9"); - cy.get(cesc2("#/p3") + " .mjx-mrow") - .eq(0) - .should("have.text", "8"); - cy.get(cesc2("#/p3") + " .mjx-mrow") - .eq(1) - .should("have.text", "0"); - cy.get(cesc2("#/p4")).should("have.text", ""); - cy.get(cesc2("#/p5") + " .mjx-mrow") - .eq(0) - .should("have.text", "7"); - cy.get(cesc2("#/p5") + " .mjx-mrow") - .eq(1) - .should("have.text", "9"); - cy.get(cesc2("#/p6") + " .mjx-mrow") - .eq(0) - .should("have.text", "8"); - cy.get(cesc2("#/p6") + " .mjx-mrow") - .eq(1) - .should("have.text", "0"); - cy.get(cesc2("#/p7")).should("have.text", ""); - - cy.get(cesc2("#/p8") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,8)"); - cy.get(cesc2("#/p8") + " .mjx-mrow") - .eq(3) - .should("not.exist"); - cy.get(cesc2("#/p9") + " .mjx-mrow") - .eq(0) - .should("have.text", "7"); - cy.get(cesc2("#/p9") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p10") + " .mjx-mrow") - .eq(0) - .should("have.text", "8"); - cy.get(cesc2("#/p10") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p11")).should("have.text", ""); - cy.get(cesc2("#/p12") + " .mjx-mrow") - .eq(0) - .should("have.text", "7"); - cy.get(cesc2("#/p12") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p13") + " .mjx-mrow") - .eq(0) - .should("have.text", "8"); - cy.get(cesc2("#/p13") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p14")).should("have.text", ""); - - cy.get(cesc2("#/p15") + " .mjx-mrow") - .eq(0) - .should("have.text", "(9,0)"); - cy.get(cesc2("#/p15") + " .mjx-mrow") - .eq(3) - .should("not.exist"); - cy.get(cesc2("#/p16") + " .mjx-mrow") - .eq(0) - .should("have.text", "9"); - cy.get(cesc2("#/p16") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p17") + " .mjx-mrow") - .eq(0) - .should("have.text", "0"); - cy.get(cesc2("#/p17") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p18")).should("have.text", ""); - cy.get(cesc2("#/p19") + " .mjx-mrow") - .eq(0) - .should("have.text", "9"); - cy.get(cesc2("#/p19") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p20") + " .mjx-mrow") - .eq(0) - .should("have.text", "0"); - cy.get(cesc2("#/p20") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p21")).should("have.text", ""); - - cy.get(cesc2("#/p22")).should("have.text", ""); - cy.get(cesc2("#/p23")).should("have.text", ""); - cy.get(cesc2("#/p24")).should("have.text", ""); - cy.get(cesc2("#/p25")).should("have.text", ""); - cy.get(cesc2("#/p26")).should("have.text", ""); - cy.get(cesc2("#/p27")).should("have.text", ""); - cy.get(cesc2("#/p28")).should("have.text", ""); - - cy.get(cesc2("#/p29")).should( - "have.text", - "\\left( 7, 8 \\right), \\left( 9, 0 \\right)", - ); - cy.get(cesc2("#/p30")).should("have.text", "7, 9"); - cy.get(cesc2("#/p31")).should("have.text", "8, 0"); - cy.get(cesc2("#/p32")).should("have.text", ""); - cy.get(cesc2("#/p33")).should("have.text", "7, 9"); - cy.get(cesc2("#/p34")).should("have.text", "8, 0"); - cy.get(cesc2("#/p35")).should("have.text", ""); - - cy.get(cesc2("#/p36")).should("have.text", "\\left( 7, 8 \\right)"); - cy.get(cesc2("#/p37")).should("have.text", "7"); - cy.get(cesc2("#/p38")).should("have.text", "8"); - cy.get(cesc2("#/p39")).should("have.text", ""); - cy.get(cesc2("#/p40")).should("have.text", "7"); - cy.get(cesc2("#/p41")).should("have.text", "8"); - cy.get(cesc2("#/p42")).should("have.text", ""); - - cy.get(cesc2("#/p43") + " .mjx-mrow") - .eq(0) - .should("have.text", "7"); - cy.get(cesc2("#/p44") + " .mjx-mrow") - .eq(0) - .should("have.text", "8"); - cy.get(cesc2("#/p45") + " .mjx-mrow") - .eq(0) - .should("have.text", "9"); - cy.get(cesc2("#/p46") + " .mjx-mrow") - .eq(0) - .should("have.text", "0"); - cy.get(cesc2("#/p47")).should("have.text", ""); - cy.get(cesc2("#/p48")).should("have.text", ""); - cy.get(cesc2("#/p49")).should("have.text", ""); - cy.get(cesc2("#/p50")).should("have.text", ""); - }); - - it("dot and array notation, chaining, specify attributes, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - -

$l.points.coords

-

$l.points.x

-

$l.points.y

-

$l.points.bad

-

$l.points.xs[1]

-

$l.points.xs[2]

-

$l.points.xs[3]

- -

$(l.points.coords{displayDecimals="4"})

-

$(l.points.x{displayDecimals="4"})

-

$(l.points.y{displayDecimals="4"})

-

$(l.points.bad{displayDecimals="4"})

-

$(l.points.xs[1]{displayDecimals="4"})

-

$(l.points.xs[2]{displayDecimals="4"})

-

$(l.points.xs[3]{displayDecimals="4"})

- -

$(l.points[1].coords{displayDecimals="4"})

-

$(l.points[1].x{displayDecimals="4"})

-

$(l.points[1].y{displayDecimals="4"})

-

$(l.points[1].bad{displayDecimals="4"})

-

$(l.points[1].xs[1]{displayDecimals="4"})

-

$(l.points[1].xs[2]{displayDecimals="4"})

-

$(l.points[1].xs[3]{displayDecimals="4"})

- -

$l.points.coords{displayDecimals="4"}

-

$l.points{displayDecimals="4"}.x

-

$l{displayDecimals="4"}.points.y

-

$l.points.bad{displayDecimals="4"}

-

$l.points.xs[1]{displayDecimals="4"}

-

$l.points{displayDecimals="4"}.xs[2]

-

$l{displayDecimals="4"}.points.xs[3]

- -

$l.points[1].coords{displayDecimals="4"}

-

$l.points[1]{displayDecimals="4"}.x

-

$l{displayDecimals="4"}.points[1].y

-

$l.points[1].bad{displayDecimals="4"}

-

$l.points[1].xs[1]{displayDecimals="4"}

-

$l.points[1]{displayDecimals="4"}.xs[2]

-

$l{displayDecimals="4"}.points[1].xs[3]

- -

$l{displayDecimals="4"}.latex

-

$(l{displayDigits="3"}.points{displayDecimals="4"})

-

$(l{displayDigits="3"}.points[1]{displayDecimals="4"})

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3.9,9.8)"); - cy.get(cesc2("#/p1") + " .mjx-mrow") - .eq(3) - .should("have.text", "(0.91,33)"); - cy.get(cesc2("#/p2") + " .mjx-mrow") - .eq(0) - .should("have.text", "3.9"); - cy.get(cesc2("#/p2") + " .mjx-mrow") - .eq(1) - .should("have.text", "0.91"); - cy.get(cesc2("#/p3") + " .mjx-mrow") - .eq(0) - .should("have.text", "9.8"); - cy.get(cesc2("#/p3") + " .mjx-mrow") - .eq(1) - .should("have.text", "33"); - cy.get(cesc2("#/p4")).should("have.text", ""); - cy.get(cesc2("#/p5") + " .mjx-mrow") - .eq(0) - .should("have.text", "3.9"); - cy.get(cesc2("#/p5") + " .mjx-mrow") - .eq(1) - .should("have.text", "0.91"); - cy.get(cesc2("#/p6") + " .mjx-mrow") - .eq(0) - .should("have.text", "9.8"); - cy.get(cesc2("#/p6") + " .mjx-mrow") - .eq(1) - .should("have.text", "33"); - cy.get(cesc2("#/p7")).should("have.text", ""); - - cy.get(cesc2("#/p8") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3.9264,9.8294)"); - cy.get(cesc2("#/p8") + " .mjx-mrow") - .eq(3) - .should("have.text", "(0.9061,32.9352)"); - cy.get(cesc2("#/p9") + " .mjx-mrow") - .eq(0) - .should("have.text", "3.9264"); - cy.get(cesc2("#/p9") + " .mjx-mrow") - .eq(1) - .should("have.text", "0.9061"); - cy.get(cesc2("#/p10") + " .mjx-mrow") - .eq(0) - .should("have.text", "9.8294"); - cy.get(cesc2("#/p10") + " .mjx-mrow") - .eq(1) - .should("have.text", "32.9352"); - cy.get(cesc2("#/p11")).should("have.text", ""); - cy.get(cesc2("#/p12") + " .mjx-mrow") - .eq(0) - .should("have.text", "3.9264"); - cy.get(cesc2("#/p12") + " .mjx-mrow") - .eq(1) - .should("have.text", "0.9061"); - cy.get(cesc2("#/p13") + " .mjx-mrow") - .eq(0) - .should("have.text", "9.8294"); - cy.get(cesc2("#/p13") + " .mjx-mrow") - .eq(1) - .should("have.text", "32.9352"); - cy.get(cesc2("#/p14")).should("have.text", ""); - - cy.get(cesc2("#/p15") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3.9264,9.8294)"); - cy.get(cesc2("#/p15") + " .mjx-mrow") - .eq(3) - .should("not.exist"); - cy.get(cesc2("#/p16") + " .mjx-mrow") - .eq(0) - .should("have.text", "3.9264"); - cy.get(cesc2("#/p16") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p17") + " .mjx-mrow") - .eq(0) - .should("have.text", "9.8294"); - cy.get(cesc2("#/p17") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p18")).should("have.text", ""); - cy.get(cesc2("#/p19") + " .mjx-mrow") - .eq(0) - .should("have.text", "3.9264"); - cy.get(cesc2("#/p19") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p20") + " .mjx-mrow") - .eq(0) - .should("have.text", "9.8294"); - cy.get(cesc2("#/p20") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p21")).should("have.text", ""); - - cy.get(cesc2("#/p22") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3.9264,9.8294)"); - cy.get(cesc2("#/p22") + " .mjx-mrow") - .eq(3) - .should("have.text", "(0.9061,32.9352)"); - cy.get(cesc2("#/p23") + " .mjx-mrow") - .eq(0) - .should("have.text", "3.9264"); - cy.get(cesc2("#/p23") + " .mjx-mrow") - .eq(1) - .should("have.text", "0.9061"); - cy.get(cesc2("#/p24") + " .mjx-mrow") - .eq(0) - .should("have.text", "9.8294"); - cy.get(cesc2("#/p24") + " .mjx-mrow") - .eq(1) - .should("have.text", "32.9352"); - cy.get(cesc2("#/p25")).should("have.text", ""); - cy.get(cesc2("#/p26") + " .mjx-mrow") - .eq(0) - .should("have.text", "3.9264"); - cy.get(cesc2("#/p26") + " .mjx-mrow") - .eq(1) - .should("have.text", "0.9061"); - cy.get(cesc2("#/p27") + " .mjx-mrow") - .eq(0) - .should("have.text", "9.8294"); - cy.get(cesc2("#/p27") + " .mjx-mrow") - .eq(1) - .should("have.text", "32.9352"); - cy.get(cesc2("#/p28")).should("have.text", ""); - - cy.get(cesc2("#/p29") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3.9264,9.8294)"); - cy.get(cesc2("#/p29") + " .mjx-mrow") - .eq(3) - .should("not.exist"); - cy.get(cesc2("#/p30") + " .mjx-mrow") - .eq(0) - .should("have.text", "3.9264"); - cy.get(cesc2("#/p30") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p31") + " .mjx-mrow") - .eq(0) - .should("have.text", "9.8294"); - cy.get(cesc2("#/p31") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p32")).should("have.text", ""); - cy.get(cesc2("#/p33") + " .mjx-mrow") - .eq(0) - .should("have.text", "3.9264"); - cy.get(cesc2("#/p33") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p34") + " .mjx-mrow") - .eq(0) - .should("have.text", "9.8294"); - cy.get(cesc2("#/p34") + " .mjx-mrow") - .eq(1) - .should("not.exist"); - cy.get(cesc2("#/p35")).should("have.text", ""); - - cy.get(cesc2("#/p36")).should( - "have.text", - "0 = -23.1058 x - 3.0203 y + 120.4105", - ); - cy.get(cesc2("#/p37") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3.9264,9.8294)"); - cy.get(cesc2("#/p37") + " .mjx-mrow") - .eq(3) - .should("have.text", "(0.9061,32.9352)"); - cy.get(cesc2("#/p38") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3.9264,9.8294)"); - cy.get(cesc2("#/p38") + " .mjx-mrow") - .eq(3) - .should("not.exist"); - }); - - it("dot and array notation, chaining, nested", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - $l.points - - -

- $l[1].points[$l.points[1].x]{displayDigits="$l.points[2].x"}.y -

-

- -

- - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "2.93521"); - cy.get(cesc2("#/p2") + " .mjx-mrow") - .eq(0) - .should("have.text", "2.93521"); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveLine", - componentName: "/l", - args: { - point1coords: [1.38527302734, 8.48273402357], - point2coords: [5.9060742037, 2.93520806203104], - }, - }); - }); - - cy.get(cesc2("#/p1") + " .mjx-mrow").should("contain.text", "8.48273"); - cy.get(cesc2("#/p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.48273"); - cy.get(cesc2("#/p2") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.48273"); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveLine", - componentName: "/l", - args: { - point1coords: [1.38527302734, 8.48273402357], - point2coords: [4.482081034234, 7.34828203481], - }, - }); - }); - - cy.get(cesc2("#/p1") + " .mjx-mrow").should("contain.text", "8.483"); - cy.get(cesc2("#/p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.483"); - cy.get(cesc2("#/p2") + " .mjx-mrow") - .eq(0) - .should("have.text", "8.483"); - }); - - it("dot and array notation, chaining, copy source, change type", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - -

-

-

-

-

-

-

- -

-

-

-

-

-

-

- -

-

-

-

-

-

-

- -

-

-

-

-

-

-

- -

-

-

-

-

-

-

- -

-

-

-

-

-

-

- -

-

-

-

-

-

-

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(23,34)"); - cy.get(cesc2("#/p1") + " .mjx-mrow") - .eq(3) - .should("have.text", "(58,35)"); - cy.get(cesc2("#/p2")).should("have.text", "0.67, 0.63"); - cy.get(cesc2("#/p3")).should("have.text", "0.75, 0.6"); - cy.get(cesc2("#/p4")).should("have.text", "NaN, NaN"); - cy.get(cesc2("#/p5")).should("have.text", "0.67, 0.63"); - cy.get(cesc2("#/p6")).should("have.text", "0.75, 0.6"); - cy.get(cesc2("#/p7")).should("have.text", "NaN, NaN"); - - cy.get(cesc2("#/p8") + " .mjx-mrow") - .eq(0) - .should("have.text", "(23,34)"); - cy.get(cesc2("#/p8") + " .mjx-mrow") - .eq(3) - .should("not.exist"); - cy.get(cesc2("#/p9")).should("have.text", "0.67"); - cy.get(cesc2("#/p10")).should("have.text", "0.75"); - cy.get(cesc2("#/p11")).should("have.text", "NaN"); - cy.get(cesc2("#/p12")).should("have.text", "0.67"); - cy.get(cesc2("#/p13")).should("have.text", "0.75"); - cy.get(cesc2("#/p14")).should("have.text", "NaN"); - - cy.get(cesc2("#/p15") + " .mjx-mrow") - .eq(0) - .should("have.text", "(58,35)"); - cy.get(cesc2("#/p15") + " .mjx-mrow") - .eq(3) - .should("not.exist"); - cy.get(cesc2("#/p16")).should("have.text", "0.63"); - cy.get(cesc2("#/p17")).should("have.text", "0.6"); - cy.get(cesc2("#/p18")).should("have.text", "NaN"); - cy.get(cesc2("#/p19")).should("have.text", "0.63"); - cy.get(cesc2("#/p20")).should("have.text", "0.6"); - cy.get(cesc2("#/p21")).should("have.text", "NaN"); - - cy.get(cesc2("#/p22") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc2("#/p23")).should("have.text", "NaN"); - cy.get(cesc2("#/p24")).should("have.text", "NaN"); - cy.get(cesc2("#/p25")).should("have.text", "NaN"); - cy.get(cesc2("#/p26")).should("have.text", "NaN"); - cy.get(cesc2("#/p27")).should("have.text", "NaN"); - cy.get(cesc2("#/p28")).should("have.text", "NaN"); - - cy.get(cesc2("#/p29")).should( - "have.text", - "\\left( \\frac{2}{3}, \\frac{3}{4} \\right), \\left( \\frac{5}{8}, \\frac{3}{5} \\right)", - ); - cy.get(cesc2("#/p30")).should( - "have.text", - "\\frac{2}{3}, \\frac{5}{8}", - ); - cy.get(cesc2("#/p31")).should( - "have.text", - "\\frac{3}{4}, \\frac{3}{5}", - ); - cy.get(cesc2("#/p32")).should("have.text", ", "); - cy.get(cesc2("#/p33")).should( - "have.text", - "\\frac{2}{3}, \\frac{5}{8}", - ); - cy.get(cesc2("#/p34")).should( - "have.text", - "\\frac{3}{4}, \\frac{3}{5}", - ); - cy.get(cesc2("#/p35")).should("have.text", ", "); - - cy.get(cesc2("#/p36")).should( - "have.text", - "\\left( \\frac{2}{3}, \\frac{3}{4} \\right)", - ); - cy.get(cesc2("#/p37")).should("have.text", "\\frac{2}{3}"); - cy.get(cesc2("#/p38")).should("have.text", "\\frac{3}{4}"); - cy.get(cesc2("#/p39")).should("have.text", ""); - cy.get(cesc2("#/p40")).should("have.text", "\\frac{2}{3}"); - cy.get(cesc2("#/p41")).should("have.text", "\\frac{3}{4}"); - cy.get(cesc2("#/p42")).should("have.text", ""); - - cy.get(cesc2("#/p43")).should("have.text", "0.67"); - cy.get(cesc2("#/p44")).should("have.text", "0.75"); - cy.get(cesc2("#/p45")).should("have.text", "0.63"); - cy.get(cesc2("#/p46")).should("have.text", "0.6"); - cy.get(cesc2("#/p47")).should("have.text", "NaN"); - cy.get(cesc2("#/p48")).should("have.text", "NaN"); - cy.get(cesc2("#/p49")).should("have.text", "NaN"); - cy.get(cesc2("#/p50")).should("have.text", "NaN"); - - cy.log("move points"); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveLine", - componentName: "/l", - args: { - point1coords: [7, 8], - point2coords: [9, 0], - }, - }); - }); - - cy.get(cesc2("#/p29")).should( - "have.text", - "\\left( 7, 8 \\right), \\left( 9, 0 \\right)", - ); - - cy.get(cesc2("#/p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,8)"); - cy.get(cesc2("#/p1") + " .mjx-mrow") - .eq(3) - .should("have.text", "(9,0)"); - cy.get(cesc2("#/p2")).should("have.text", "7, 9"); - cy.get(cesc2("#/p3")).should("have.text", "8, 0"); - cy.get(cesc2("#/p4")).should("have.text", "NaN, NaN"); - cy.get(cesc2("#/p5")).should("have.text", "7, 9"); - cy.get(cesc2("#/p6")).should("have.text", "8, 0"); - cy.get(cesc2("#/p7")).should("have.text", "NaN, NaN"); - - cy.get(cesc2("#/p8") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,8)"); - cy.get(cesc2("#/p8") + " .mjx-mrow") - .eq(3) - .should("not.exist"); - cy.get(cesc2("#/p9")).should("have.text", "7"); - cy.get(cesc2("#/p10")).should("have.text", "8"); - cy.get(cesc2("#/p11")).should("have.text", "NaN"); - cy.get(cesc2("#/p12")).should("have.text", "7"); - cy.get(cesc2("#/p13")).should("have.text", "8"); - cy.get(cesc2("#/p14")).should("have.text", "NaN"); - - cy.get(cesc2("#/p15") + " .mjx-mrow") - .eq(0) - .should("have.text", "(9,0)"); - cy.get(cesc2("#/p15") + " .mjx-mrow") - .eq(3) - .should("not.exist"); - cy.get(cesc2("#/p16")).should("have.text", "9"); - cy.get(cesc2("#/p17")).should("have.text", "0"); - cy.get(cesc2("#/p18")).should("have.text", "NaN"); - cy.get(cesc2("#/p19")).should("have.text", "9"); - cy.get(cesc2("#/p20")).should("have.text", "0"); - cy.get(cesc2("#/p21")).should("have.text", "NaN"); - - cy.get(cesc2("#/p22") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc2("#/p23")).should("have.text", "NaN"); - cy.get(cesc2("#/p24")).should("have.text", "NaN"); - cy.get(cesc2("#/p25")).should("have.text", "NaN"); - cy.get(cesc2("#/p26")).should("have.text", "NaN"); - cy.get(cesc2("#/p27")).should("have.text", "NaN"); - cy.get(cesc2("#/p28")).should("have.text", "NaN"); - - cy.get(cesc2("#/p29")).should( - "have.text", - "\\left( 7, 8 \\right), \\left( 9, 0 \\right)", - ); - cy.get(cesc2("#/p30")).should("have.text", "7, 9"); - cy.get(cesc2("#/p31")).should("have.text", "8, 0"); - cy.get(cesc2("#/p32")).should("have.text", ", "); - cy.get(cesc2("#/p33")).should("have.text", "7, 9"); - cy.get(cesc2("#/p34")).should("have.text", "8, 0"); - cy.get(cesc2("#/p35")).should("have.text", ", "); - - cy.get(cesc2("#/p36")).should("have.text", "\\left( 7, 8 \\right)"); - cy.get(cesc2("#/p37")).should("have.text", "7"); - cy.get(cesc2("#/p38")).should("have.text", "8"); - cy.get(cesc2("#/p39")).should("have.text", ""); - cy.get(cesc2("#/p40")).should("have.text", "7"); - cy.get(cesc2("#/p41")).should("have.text", "8"); - cy.get(cesc2("#/p42")).should("have.text", ""); - - cy.get(cesc2("#/p43")).should("have.text", "7"); - cy.get(cesc2("#/p44")).should("have.text", "8"); - cy.get(cesc2("#/p45")).should("have.text", "9"); - cy.get(cesc2("#/p46")).should("have.text", "0"); - cy.get(cesc2("#/p47")).should("have.text", "NaN"); - cy.get(cesc2("#/p48")).should("have.text", "NaN"); - cy.get(cesc2("#/p49")).should("have.text", "NaN"); - cy.get(cesc2("#/p50")).should("have.text", "NaN"); - }); - - it("dot and array notation, multidimensional, dynamic", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - -

Line number:

-

Point number:

-

Coordinate number:

- - -

$col[$ln].points[$pn][$cn]

-

-

$col[$ln].points[$pn].xs[$cn]

-

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc2("#/p2") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc2("#/p3") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc2("#/p4") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - - cy.get(cesc2("#/ln") + " textarea").type("{end}{backspace}{enter}", { - force: true, - }); - - cy.get(cesc2("#/p1")).should("have.text", ""); - cy.get(cesc2("#/p2")).should("have.text", ""); - cy.get(cesc2("#/p3")).should("have.text", ""); - cy.get(cesc2("#/p4")).should("have.text", ""); - - cy.get(cesc2("#/ln") + " textarea").type("2{enter}", { force: true }); - - cy.get(cesc2("#/p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - cy.get(cesc2("#/p2") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - cy.get(cesc2("#/p3") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - cy.get(cesc2("#/p4") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - - cy.get(cesc2("#/pn") + " textarea").type("{end}{backspace}{enter}", { - force: true, - }); - - cy.get(cesc2("#/p1")).should("have.text", ""); - cy.get(cesc2("#/p2")).should("have.text", ""); - cy.get(cesc2("#/p3")).should("have.text", ""); - cy.get(cesc2("#/p4")).should("have.text", ""); - - cy.get(cesc2("#/pn") + " textarea").type("2{enter}", { force: true }); - - cy.get(cesc2("#/p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "9"); - cy.get(cesc2("#/p2") + " .mjx-mrow") - .eq(0) - .should("have.text", "9"); - cy.get(cesc2("#/p3") + " .mjx-mrow") - .eq(0) - .should("have.text", "9"); - cy.get(cesc2("#/p4") + " .mjx-mrow") - .eq(0) - .should("have.text", "9"); - - cy.get(cesc2("#/cn") + " textarea").type("{end}{backspace}{enter}", { - force: true, - }); - - cy.get(cesc2("#/p1")).should("have.text", ""); - cy.get(cesc2("#/p2")).should("have.text", ""); - cy.get(cesc2("#/p3")).should("have.text", ""); - cy.get(cesc2("#/p4")).should("have.text", ""); - - cy.get(cesc2("#/cn") + " textarea").type("2{enter}", { force: true }); - - cy.get(cesc2("#/p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc2("#/p2") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc2("#/p3") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - cy.get(cesc2("#/p4") + " .mjx-mrow") - .eq(0) - .should("have.text", "6"); - }); - - it("dot and array notation, recurse to subnames of composite replacements", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

n:

- - - - - - -

Template number:

-

Point number:

-

Coordinate number:

- -

The points from template $tn are: $(myMap[$tn]/P) and .

-

Point $pn from the line in that template is: $(myMap[$tn]/l.points[$pn]).

-

Coordinate $cn from that point is $(myMap[$tn]/l.points[$pn].xs[$cn]).

-

Again, coordinate $cn from that point is .

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let Pxs = [2, 3, 4, 5, 6]; - let Pys = [3, 4, 5, 6, 7]; - let Qxs = [5, 6, 7, 8, 9]; - let Qys = [0, 1, 2, 3, 4]; - - function checkResult(n, tn, pn, cn) { - if (!(n >= 1 && tn <= n)) { - // we have nothing - cy.get(cesc("#\\/pt")).should("contain.text", "are: and ."); - cy.get(cesc("#\\/pp")).should( - "contain.text", - " from the line in that template is: .", - ); - cy.get(cesc("#\\/pc")).should( - "contain.text", - "from that point is .", - ); - cy.get(cesc("#\\/pc2")).should( - "contain.text", - "from that point is .", - ); - } else { - cy.get(cesc("#\\/pt") + " .mjx-mrow").should( - "contain.text", - `(${Pxs[tn - 1]},${Pys[tn - 1]})`, - ); - cy.get(cesc("#\\/pt") + " .mjx-mrow").should( - "contain.text", - `(${Qxs[tn - 1]},${Qys[tn - 1]})`, - ); - cy.get(cesc("#\\/pt") + " .mjx-mrow") - .eq(1) - .should("have.text", `(${Pxs[tn - 1]},${Pys[tn - 1]})`); - cy.get(cesc("#\\/pt") + " .mjx-mrow") - .eq(4) - .should("have.text", `(${Qxs[tn - 1]},${Qys[tn - 1]})`); - - if (pn === 1) { - cy.get(cesc("#\\/pp") + " .mjx-mrow").should( - "contain.text", - `(${Pxs[tn - 1]},${Pys[tn - 1]})`, - ); - cy.get(cesc("#\\/pp") + " .mjx-mrow") - .eq(1) - .should("have.text", `(${Pxs[tn - 1]},${Pys[tn - 1]})`); - if (cn === 1) { - cy.get(cesc("#\\/pc") + " .mjx-mrow").should( - "contain.text", - `${Pxs[tn - 1]}`, - ); - cy.get(cesc("#\\/pc2") + " .mjx-mrow").should( - "contain.text", - `${Pxs[tn - 1]}`, - ); - cy.get(cesc("#\\/pc") + " .mjx-mrow") - .eq(1) - .should("have.text", `${Pxs[tn - 1]}`); - cy.get(cesc("#\\/pc2") + " .mjx-mrow") - .eq(1) - .should("have.text", `${Pxs[tn - 1]}`); - } else if (cn === 2) { - cy.get(cesc("#\\/pc") + " .mjx-mrow").should( - "contain.text", - `${Pys[tn - 1]}`, - ); - cy.get(cesc("#\\/pc2") + " .mjx-mrow").should( - "contain.text", - `${Pys[tn - 1]}`, - ); - cy.get(cesc("#\\/pc") + " .mjx-mrow") - .eq(1) - .should("have.text", `${Pys[tn - 1]}`); - cy.get(cesc("#\\/pc2") + " .mjx-mrow") - .eq(1) - .should("have.text", `${Pys[tn - 1]}`); - } else { - cy.get(cesc("#\\/pc")).should( - "contain.text", - "from that point is .", - ); - cy.get(cesc("#\\/pc2")).should( - "contain.text", - "from that point is .", - ); - } - } else if (pn === 2) { - cy.get(cesc("#\\/pp") + " .mjx-mrow").should( - "contain.text", - `(${Qxs[tn - 1]},${Qys[tn - 1]})`, - ); - cy.get(cesc("#\\/pp") + " .mjx-mrow") - .eq(1) - .should("have.text", `(${Qxs[tn - 1]},${Qys[tn - 1]})`); - if (cn === 1) { - cy.get(cesc("#\\/pc") + " .mjx-mrow").should( - "contain.text", - `${Qxs[tn - 1]}`, - ); - cy.get(cesc("#\\/pc2") + " .mjx-mrow").should( - "contain.text", - `${Qxs[tn - 1]}`, - ); - cy.get(cesc("#\\/pc") + " .mjx-mrow") - .eq(1) - .should("have.text", `${Qxs[tn - 1]}`); - cy.get(cesc("#\\/pc2") + " .mjx-mrow") - .eq(1) - .should("have.text", `${Qxs[tn - 1]}`); - } else if (cn === 2) { - cy.get(cesc("#\\/pc") + " .mjx-mrow").should( - "contain.text", - `${Qys[tn - 1]}`, - ); - cy.get(cesc("#\\/pc2") + " .mjx-mrow").should( - "contain.text", - `${Qys[tn - 1]}`, - ); - cy.get(cesc("#\\/pc") + " .mjx-mrow") - .eq(1) - .should("have.text", `${Qys[tn - 1]}`); - cy.get(cesc("#\\/pc2") + " .mjx-mrow") - .eq(1) - .should("have.text", `${Qys[tn - 1]}`); - } else { - cy.get(cesc("#\\/pc")).should( - "contain.text", - "from that point is .", - ); - cy.get(cesc("#\\/pc2")).should( - "contain.text", - "from that point is .", - ); - } - } else { - cy.get(cesc("#\\/pp")).should( - "contain.text", - " from the line in that template is: .", - ); - cy.get(cesc("#\\/pc")).should( - "contain.text", - "from that point is .", - ); - cy.get(cesc("#\\/pc2")).should( - "contain.text", - "from that point is .", - ); - } - } - } - - checkResult(2, 1, 1, 1); - - cy.get(cesc("#\\/tn") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - checkResult(2, 2, 1, 1); - - cy.get(cesc("#\\/tn") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - checkResult(2, 3, 1, 1); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}4{enter}", { - force: true, - }); - checkResult(4, 3, 1, 1); - - cy.get(cesc("#\\/pn") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - checkResult(4, 3, 3, 1); - - cy.get(cesc("#\\/pn") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - checkResult(4, 3, 2, 1); - - cy.get(cesc("#\\/cn") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - checkResult(4, 3, 2, 3); - - cy.get(cesc("#\\/cn") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - checkResult(4, 3, 2, 2); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - checkResult(3, 3, 2, 2); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}1{enter}", { - force: true, - }); - checkResult(1, 3, 2, 2); - - cy.get(cesc("#\\/tn") + " textarea").type("{end}{backspace}1{enter}", { - force: true, - }); - checkResult(1, 1, 2, 2); - }); - - it("dot and array notation from group", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - x - copied will be blank - hello - copied will also be blank - (4,5) - -

A y and a word.

-
- -

the math: $grp[1]

-

a blank: $grp[2]

-

the text: $grp[3]

-

another blank: $grp[4]

-

the point: $grp[5]

-

the point x: $grp[5].x

-

the line: $grp[6]

-

the line, point 1: $grp[6].points[1]

-

the line, point 2, y: $grp[6].points[2].y

-

math from p: $(grp[7]/m)

-

text from p: $(grp[7]/t)

-

nothing: $grp[8]

-

Prop fixed from group: $grp.fixed

-

Prop x from group: $grp.x

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/p2")).should("have.text", "a blank: "); - cy.get(cesc2("#/p3")).should("have.text", "the text: hello"); - cy.get(cesc2("#/p4")).should("have.text", "another blank: "); - cy.get(cesc2("#/p5") + " .mjx-mrow") - .eq(0) - .should("have.text", "(4,5)"); - cy.get(cesc2("#/p6") + " .mjx-mrow") - .eq(0) - .should("have.text", "4"); - cy.get(cesc2("#/p7") + " .mjx-mrow") - .eq(0) - .should("have.text", "0=x−y−1"); - cy.get(cesc2("#/p8") + " .mjx-mrow") - .eq(0) - .should("have.text", "(10,9)"); - cy.get(cesc2("#/p9") + " .mjx-mrow") - .eq(0) - .should("have.text", "8"); - cy.get(cesc2("#/p10") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/p11")).should("have.text", "text from p: word"); - cy.get(cesc2("#/p12")).should("have.text", "nothing: "); - cy.get(cesc2("#/p13")).should( - "have.text", - "Prop fixed from group: false, true, false, false, false", - ); - cy.get(cesc2("#/p14")).should("contain.text", "Prop x from group: x"); - cy.get(cesc2("#/p14")).should("contain.text", "x, 4"); - cy.get(cesc2("#/p14") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/p14") + " .mjx-mrow") - .eq(1) - .should("have.text", "4"); - }); - - it("implicitProp from an input", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

$mi

-

$mi{simplify}

-

$mi

-

-

-

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/pmacro1") + " .mjx-mrow") - .eq(0) - .should("have.text", "x+x"); - cy.get(cesc2("#/pmacro2") + " .mjx-mrow") - .eq(0) - .should("have.text", "2x"); - - cy.get(cesc2("#/pcopy1") + " .mjx-mrow") - .eq(0) - .should("have.text", "x+x"); - cy.get(cesc2("#/pcopy2") + " .mjx-mrow") - .eq(0) - .should("have.text", "2x"); - cy.get(cesc2("#/pcopy3") + " .mjx-mrow") - .eq(0) - .should("have.text", "2x"); - cy.get(cesc2("#/pcopy4") + " .mq-editable-field") - .eq(0) - .should("have.text", "x+x"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let macrom1Name = - stateVariables["/pmacro1"].activeChildren[0].componentName; - let macrom2Name = - stateVariables["/pmacro2"].activeChildren[0].componentName; - let copym1Name = - stateVariables["/pcopy1"].activeChildren[0].componentName; - let copym2Name = - stateVariables["/pcopy2"].activeChildren[0].componentName; - let copym3Name = - stateVariables["/pcopy3"].activeChildren[0].componentName; - let copymi4Name = - stateVariables["/pcopy4"].activeChildren[0].componentName; - - expect(stateVariables[macrom1Name].componentType).eq("math"); - expect(stateVariables[macrom2Name].componentType).eq("math"); - expect(stateVariables[copym1Name].componentType).eq("math"); - expect(stateVariables[copym2Name].componentType).eq("math"); - expect(stateVariables[copym3Name].componentType).eq("math"); - expect(stateVariables[copymi4Name].componentType).eq("mathInput"); - expect(stateVariables[macrom1Name].stateValues.value).eqls([ - "+", - "x", - "x", - ]); - expect(stateVariables[macrom2Name].stateValues.value).eqls([ - "*", - 2, - "x", - ]); - expect(stateVariables[copym1Name].stateValues.value).eqls([ - "+", - "x", - "x", - ]); - expect(stateVariables[copym2Name].stateValues.value).eqls([ - "*", - 2, - "x", - ]); - expect(stateVariables[copym3Name].stateValues.value).eqls([ - "*", - 2, - "x", - ]); - expect(stateVariables[copymi4Name].stateValues.value).eqls([ - "+", - "x", - "x", - ]); - }); - }); - - it("implicitProp with same componentType depend on attributes", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - x+x - $m{name="mimplicit1"} - $m{name="mimplicit2" createComponentOfType="math"} - - $m{name="mnotimplicit1" newNamespace} - $m{name="mnotimplicit2" newNamespace createComponentOfType="math"} - - $m{name="mnotimplicit4" simplify="false"} - $m{name="mnotimplicit5" simplify="false" createComponentOfType="math"} - - - $(mnotimplicit2/msub{name="msubimplicit1"}) - $(mnotimplicit3/msub{name="msubimplicit2"}) - - - - y+z - $n{name="nnotimplicit1"} - - $(nnotimplicit2/nsub{name="nsubimplicit1"}) - - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/mimplicit1") + " .mjx-mrow") - .eq(0) - .should("have.text", "2x"); - cy.get(cesc2("#/mimplicit2") + " .mjx-mrow") - .eq(0) - .should("have.text", "2x"); - cy.get(cesc2("#/mimplicit3") + " .mjx-mrow") - .eq(0) - .should("have.text", "2x"); - cy.get(cesc2("#/mnotimplicit1") + " .mjx-mrow") - .eq(0) - .should("have.text", "2x"); - cy.get(cesc2("#/mnotimplicit2") + " .mjx-mrow") - .eq(0) - .should("have.text", "2x"); - cy.get(cesc2("#/mnotimplicit3") + " .mjx-mrow") - .eq(0) - .should("have.text", "2x"); - cy.get(cesc2("#/mnotimplicit4") + " .mjx-mrow") - .eq(0) - .should("have.text", "x+x"); - cy.get(cesc2("#/mnotimplicit5") + " .mjx-mrow") - .eq(0) - .should("have.text", "x+x"); - cy.get(cesc2("#/mnotimplicit6") + " .mjx-mrow") - .eq(0) - .should("have.text", "x+x"); - cy.get(cesc2("#/msubimplicit1") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/msubimplicit2") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/msubimplicit3") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - - cy.get(cesc2("#/nnotimplicit1") + " .mjx-mrow") - .eq(0) - .should("have.text", "y+z"); - cy.get(cesc2("#/nnotimplicit2") + " .mjx-mrow") - .eq(0) - .should("have.text", "y+z"); - cy.get(cesc2("#/nsubimplicit1") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/nsubimplicit2") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mimplicit1"].activeChildren.length).eq(0); - expect(stateVariables["/mimplicit2"].activeChildren.length).eq(0); - expect(stateVariables["/mimplicit3"].activeChildren.length).eq(0); - expect(stateVariables["/mnotimplicit1"].activeChildren.length).eq( - 2, - ); - expect(stateVariables["/mnotimplicit2"].activeChildren.length).eq( - 2, - ); - expect(stateVariables["/mnotimplicit3"].activeChildren.length).eq( - 2, - ); - expect(stateVariables["/mnotimplicit4"].activeChildren.length).eq( - 2, - ); - expect(stateVariables["/mnotimplicit5"].activeChildren.length).eq( - 2, - ); - expect(stateVariables["/mnotimplicit6"].activeChildren.length).eq( - 2, - ); - expect(stateVariables["/msubimplicit1"].activeChildren.length).eq( - 0, - ); - expect(stateVariables["/msubimplicit2"].activeChildren.length).eq( - 0, - ); - expect(stateVariables["/msubimplicit3"].activeChildren.length).eq( - 0, - ); - - expect(stateVariables["/nnotimplicit1"].activeChildren.length).eq( - 2, - ); - expect(stateVariables["/nnotimplicit2"].activeChildren.length).eq( - 2, - ); - expect(stateVariables["/nsubimplicit1"].activeChildren.length).eq( - 0, - ); - expect(stateVariables["/nsubimplicit2"].activeChildren.length).eq( - 0, - ); - }); - }); - - it("implicitProp with same componentType depend on attributes, subnames", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - - 1 - - - $(map[1]/m{name="mimplicit1"}) - $(map[1]/m{name="mimplicit2" createComponentOfType="math"}) - - $(map[1]/m{name="mnotimplicit1" newNamespace}) - $(map[1]/m{name="mnotimplicit2" newNamespace createComponentOfType="math"}) - - $(map[1]/m{name="mnotimplicit4" simplify="false"}) - $(map[1]/m{name="mnotimplicit5" simplify="false" createComponentOfType="math"}) - - - $(mnotimplicit2/msub{name="msubimplicit1"}) - $(mnotimplicit3/msub{name="msubimplicit2"}) - - - - - 1 - - - $(map2[1]/n{name="nnotimplicit1"}) - - $(nnotimplicit2/nsub{name="nsubimplicit1"}) - - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/mimplicit1") + " .mjx-mrow") - .eq(0) - .should("have.text", "2x"); - cy.get(cesc2("#/mimplicit2") + " .mjx-mrow") - .eq(0) - .should("have.text", "2x"); - cy.get(cesc2("#/mimplicit3") + " .mjx-mrow") - .eq(0) - .should("have.text", "2x"); - cy.get(cesc2("#/mnotimplicit1") + " .mjx-mrow") - .eq(0) - .should("have.text", "2x"); - cy.get(cesc2("#/mnotimplicit2") + " .mjx-mrow") - .eq(0) - .should("have.text", "2x"); - cy.get(cesc2("#/mnotimplicit3") + " .mjx-mrow") - .eq(0) - .should("have.text", "2x"); - cy.get(cesc2("#/mnotimplicit4") + " .mjx-mrow") - .eq(0) - .should("have.text", "x+x"); - cy.get(cesc2("#/mnotimplicit5") + " .mjx-mrow") - .eq(0) - .should("have.text", "x+x"); - cy.get(cesc2("#/mnotimplicit6") + " .mjx-mrow") - .eq(0) - .should("have.text", "x+x"); - cy.get(cesc2("#/msubimplicit1") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/msubimplicit2") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/msubimplicit3") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - - cy.get(cesc2("#/nnotimplicit1") + " .mjx-mrow") - .eq(0) - .should("have.text", "y+z"); - cy.get(cesc2("#/nnotimplicit2") + " .mjx-mrow") - .eq(0) - .should("have.text", "y+z"); - cy.get(cesc2("#/nsubimplicit1") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - cy.get(cesc2("#/nsubimplicit2") + " .mjx-mrow") - .eq(0) - .should("have.text", "y"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/mimplicit1"].activeChildren.length).eq(0); - expect(stateVariables["/mimplicit2"].activeChildren.length).eq(0); - expect(stateVariables["/mimplicit3"].activeChildren.length).eq(0); - expect(stateVariables["/mnotimplicit1"].activeChildren.length).eq( - 2, - ); - expect(stateVariables["/mnotimplicit2"].activeChildren.length).eq( - 2, - ); - expect(stateVariables["/mnotimplicit3"].activeChildren.length).eq( - 2, - ); - expect(stateVariables["/mnotimplicit4"].activeChildren.length).eq( - 2, - ); - expect(stateVariables["/mnotimplicit5"].activeChildren.length).eq( - 2, - ); - expect(stateVariables["/mnotimplicit6"].activeChildren.length).eq( - 2, - ); - expect(stateVariables["/msubimplicit1"].activeChildren.length).eq( - 0, - ); - expect(stateVariables["/msubimplicit2"].activeChildren.length).eq( - 0, - ); - expect(stateVariables["/msubimplicit3"].activeChildren.length).eq( - 0, - ); - - expect(stateVariables["/nnotimplicit1"].activeChildren.length).eq( - 2, - ); - expect(stateVariables["/nnotimplicit2"].activeChildren.length).eq( - 2, - ); - expect(stateVariables["/nsubimplicit1"].activeChildren.length).eq( - 0, - ); - expect(stateVariables["/nsubimplicit2"].activeChildren.length).eq( - 0, - ); - }); - }); - - it("copies of composites ignore implicitProp", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - -

- -

$col

- -

$col

- -

$g

- -

$g

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/pmacro") + " .mq-editable-field") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/pmacro") + " .mq-editable-field") - .eq(1) - .should("have.text", "y"); - - cy.get(cesc2("#/pcopy") + " .mq-editable-field") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/pcopy") + " .mq-editable-field") - .eq(1) - .should("have.text", "y"); - - cy.get(cesc2("#/pmacro2") + " .mq-editable-field") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/pmacro2") + " .mq-editable-field") - .eq(1) - .should("have.text", "y"); - - cy.get(cesc2("#/pcopy2") + " .mq-editable-field") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/pcopy2") + " .mq-editable-field") - .eq(1) - .should("have.text", "y"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let [macromi1Name, macromi2Name] = stateVariables[ - "/pmacro" - ].activeChildren.map((x) => x.componentName); - let [copymi1Name, copymi2Name] = stateVariables[ - "/pcopy" - ].activeChildren.map((x) => x.componentName); - let [macromi1Name2, macromi2Name2] = stateVariables[ - "/pmacro2" - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - let [copymi1Name2, copymi2Name2] = stateVariables[ - "/pcopy2" - ].activeChildren - .filter((x) => x.componentName) - .map((x) => x.componentName); - - expect(stateVariables[macromi1Name].componentType).eq("mathInput"); - expect(stateVariables[macromi2Name].componentType).eq("mathInput"); - expect(stateVariables[copymi1Name].componentType).eq("mathInput"); - expect(stateVariables[copymi2Name].componentType).eq("mathInput"); - expect(stateVariables[macromi1Name].stateValues.value).eq("x"); - expect(stateVariables[macromi2Name].stateValues.value).eq("y"); - expect(stateVariables[copymi1Name].stateValues.value).eq("x"); - expect(stateVariables[copymi2Name].stateValues.value).eq("y"); - expect(stateVariables[macromi1Name2].componentType).eq("mathInput"); - expect(stateVariables[macromi2Name2].componentType).eq("mathInput"); - expect(stateVariables[copymi1Name2].componentType).eq("mathInput"); - expect(stateVariables[copymi2Name2].componentType).eq("mathInput"); - expect(stateVariables[macromi1Name2].stateValues.value).eq("x"); - expect(stateVariables[macromi2Name2].stateValues.value).eq("y"); - expect(stateVariables[copymi1Name2].stateValues.value).eq("x"); - expect(stateVariables[copymi2Name2].stateValues.value).eq("y"); - }); - }); - - it("copies of composites with subnames do not ignore implicitProp", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - xy - - -

$map

-

$map

- -

$map[1]$map[2]

-

- -

$(map[1]/mi)$(map[2]/mi)

-

- - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/pmacro") + " .mq-editable-field") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/pmacro") + " .mq-editable-field") - .eq(1) - .should("have.text", "y"); - - cy.get(cesc2("#/pcopy") + " .mq-editable-field") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/pcopy") + " .mq-editable-field") - .eq(1) - .should("have.text", "y"); - - cy.get(cesc2("#/pmacroInd") + " .mq-editable-field") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/pmacroInd") + " .mq-editable-field") - .eq(1) - .should("have.text", "y"); - - cy.get(cesc2("#/pcopyInd") + " .mq-editable-field") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/pcopyInd") + " .mq-editable-field") - .eq(1) - .should("have.text", "y"); - - cy.get(cesc2("#/pmacroSubname") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/pmacroSubname") + " .mjx-mrow") - .eq(1) - .should("have.text", "y"); - - cy.get(cesc2("#/pcopySubname") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc2("#/pcopySubname") + " .mjx-mrow") - .eq(1) - .should("have.text", "y"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let [macromi1Name, macromi2Name] = stateVariables[ - "/pmacro" - ].activeChildren.map((x) => x.componentName); - let [copymi1Name, copymi2Name] = stateVariables[ - "/pcopy" - ].activeChildren.map((x) => x.componentName); - let [macroIndmi1Name, macroIndmi2Name] = stateVariables[ - "/pmacroInd" - ].activeChildren.map((x) => x.componentName); - let [copyIndmi1Name, copyIndmi2Name] = stateVariables[ - "/pmacroInd" - ].activeChildren.map((x) => x.componentName); - let [macroSubnamem1Name, macroSubnamem2Name] = stateVariables[ - "/pmacroSubname" - ].activeChildren.map((x) => x.componentName); - let [copySubnamem1Name, copySubnamem2Name] = stateVariables[ - "/pcopySubname" - ].activeChildren.map((x) => x.componentName); - - expect(stateVariables[macromi1Name].componentType).eq("mathInput"); - expect(stateVariables[macromi2Name].componentType).eq("mathInput"); - expect(stateVariables[copymi1Name].componentType).eq("mathInput"); - expect(stateVariables[copymi2Name].componentType).eq("mathInput"); - expect(stateVariables[macroIndmi1Name].componentType).eq( - "mathInput", - ); - expect(stateVariables[macroIndmi2Name].componentType).eq( - "mathInput", - ); - expect(stateVariables[copyIndmi1Name].componentType).eq( - "mathInput", - ); - expect(stateVariables[copyIndmi2Name].componentType).eq( - "mathInput", - ); - expect(stateVariables[macroSubnamem1Name].componentType).eq("math"); - expect(stateVariables[macroSubnamem2Name].componentType).eq("math"); - expect(stateVariables[copySubnamem1Name].componentType).eq("math"); - expect(stateVariables[copySubnamem2Name].componentType).eq("math"); - expect(stateVariables[macromi1Name].stateValues.value).eq("x"); - expect(stateVariables[macromi2Name].stateValues.value).eq("y"); - expect(stateVariables[copymi1Name].stateValues.value).eq("x"); - expect(stateVariables[copymi2Name].stateValues.value).eq("y"); - expect(stateVariables[macroIndmi1Name].stateValues.value).eq("x"); - expect(stateVariables[macroIndmi2Name].stateValues.value).eq("y"); - expect(stateVariables[copyIndmi1Name].stateValues.value).eq("x"); - expect(stateVariables[copyIndmi2Name].stateValues.value).eq("y"); - expect(stateVariables[macroSubnamem1Name].stateValues.value).eq( - "x", - ); - expect(stateVariables[macroSubnamem2Name].stateValues.value).eq( - "y", - ); - expect(stateVariables[copySubnamem1Name].stateValues.value).eq("x"); - expect(stateVariables[copySubnamem2Name].stateValues.value).eq("y"); - }); - }); - - it("implicitProp with createComponentOfType", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- -

$mi{createComponentOfType='mathinput'}, $mi, $mi{createComponentOfType='math'}

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/_math1") + " .mjx-mrow").should( - "contain.text", - "\uff3f", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let mi3Anchor = cesc2( - "#" + stateVariables["/_p2"].activeChildren[0].componentName, - ); - let m2Anchor = cesc2( - "#" + stateVariables["/_p2"].activeChildren[2].componentName, - ); - let m3Anchor = cesc2( - "#" + stateVariables["/_p2"].activeChildren[4].componentName, - ); - - cy.get(m2Anchor + " .mjx-mrow").should("contain.text", "\uff3f"); - cy.get(m3Anchor + " .mjx-mrow").should("contain.text", "\uff3f"); - - cy.log("mathinputs change with immediate value"); - cy.get(cesc("#\\/mi") + " textarea").type("x", { force: true }); - - cy.get(cesc("#\\/_mathinput2") + " .mq-editable-field").should( - "have.text", - "x", - ); - cy.get(mi3Anchor + " .mq-editable-field").should("have.text", "x"); - - cy.get(cesc("#\\/_math1") + " .mjx-mrow").should( - "contain.text", - "\uff3f", - ); - cy.get(m2Anchor + " .mjx-mrow").should("contain.text", "\uff3f"); - cy.get(m3Anchor + " .mjx-mrow").should("contain.text", "\uff3f"); - - cy.log("maths change with value"); - cy.get(cesc("#\\/mi") + " textarea").blur(); - - cy.get(cesc("#\\/_math1") + " .mjx-mrow").should( - "contain.text", - "x", - ); - cy.get(m2Anchor + " .mjx-mrow").should("contain.text", "x"); - cy.get(m3Anchor + " .mjx-mrow").should("contain.text", "x"); - - cy.log("mathinputs change with immediate value"); - cy.get(cesc("#\\/_mathinput2") + " textarea").type( - "{end}{backspace}y", - { - force: true, - }, - ); - - cy.get(cesc("#\\/mi") + " .mq-editable-field").should( - "have.text", - "y", - ); - cy.get(mi3Anchor + " .mq-editable-field").should("have.text", "y"); - - cy.get(cesc("#\\/_math1") + " .mjx-mrow").should( - "contain.text", - "x", - ); - cy.get(m2Anchor + " .mjx-mrow").should("contain.text", "x"); - cy.get(m3Anchor + " .mjx-mrow").should("contain.text", "x"); - - cy.log("maths change with value"); - cy.get(cesc("#\\/_mathinput2") + " textarea").blur(); - - cy.get(cesc("#\\/_math1") + " .mjx-mrow").should( - "contain.text", - "y", - ); - cy.get(m2Anchor + " .mjx-mrow").should("contain.text", "y"); - cy.get(m3Anchor + " .mjx-mrow").should("contain.text", "y"); - - cy.log("mathinputs change with immediate value"); - cy.get(mi3Anchor + " textarea").type("{end}{backspace}z", { - force: true, - }); - - cy.get(cesc("#\\/mi") + " .mq-editable-field").should( - "have.text", - "z", - ); - cy.get(cesc("#\\/_mathinput2") + " .mq-editable-field").should( - "have.text", - "z", - ); - - cy.get(cesc("#\\/_math1") + " .mjx-mrow").should( - "contain.text", - "y", - ); - cy.get(m2Anchor + " .mjx-mrow").should("contain.text", "y"); - cy.get(m3Anchor + " .mjx-mrow").should("contain.text", "y"); - - cy.log("maths change with value"); - cy.get(mi3Anchor + " textarea").blur(); - - cy.get(cesc("#\\/_math1") + " .mjx-mrow").should( - "contain.text", - "z", - ); - cy.get(m2Anchor + " .mjx-mrow").should("contain.text", "z"); - cy.get(m3Anchor + " .mjx-mrow").should("contain.text", "z"); - }); - }); - - it("asList when copy array prop", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - yes - no - maybe - - -

Default: $ci.choiceTexts

-

No commas: $ci.choiceTexts{asList="false"}

-

With commas: $ci.choiceTexts{asList="true"}

-

-

-

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/default")).should( - "have.text", - "Default: yes, no, maybe", - ); - cy.get(cesc2("#/nocommas")).should( - "have.text", - "No commas: yesnomaybe", - ); - cy.get(cesc2("#/withcommas")).should( - "have.text", - "With commas: yes, no, maybe", - ); - cy.get(cesc2("#/default2")).should( - "have.text", - "Default: yes, no, maybe", - ); - cy.get(cesc2("#/nocommas2")).should( - "have.text", - "No commas: yesnomaybe", - ); - cy.get(cesc2("#/withcommas2")).should( - "have.text", - "With commas: yes, no, maybe", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/default"].stateValues.text).eq( - "Default: yes, no, maybe", - ); - expect(stateVariables["/nocommas"].stateValues.text).eq( - "No commas: yesnomaybe", - ); - expect(stateVariables["/withcommas"].stateValues.text).eq( - "With commas: yes, no, maybe", - ); - expect(stateVariables["/default2"].stateValues.text).eq( - "Default: yes, no, maybe", - ); - expect(stateVariables["/nocommas2"].stateValues.text).eq( - "No commas: yesnomaybe", - ); - expect(stateVariables["/withcommas2"].stateValues.text).eq( - "With commas: yes, no, maybe", - ); - }); - }); - - it("asList when copy array prop, multiple stacked props", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - -

Default: $l.points.x

-

No commas: $l.points.x{asList="false"}

-

With commas: $l.points.x{asList="true"}

-

-

-

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/default")).should("contain.text", "1, 3"); - cy.get(cesc2("#/nocommas")).should("contain.text", "13"); - cy.get(cesc2("#/withcommas")).should("contain.text", "1, 3"); - cy.get(cesc2("#/default2")).should("contain.text", "1, 3"); - cy.get(cesc2("#/nocommas2")).should("contain.text", "13"); - cy.get(cesc2("#/withcommas2")).should("contain.text", "1, 3"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/default"].stateValues.text).eq( - "Default: 1, 3", - ); - expect(stateVariables["/nocommas"].stateValues.text).eq( - "No commas: 13", - ); - expect(stateVariables["/withcommas"].stateValues.text).eq( - "With commas: 1, 3", - ); - expect(stateVariables["/default2"].stateValues.text).eq( - "Default: 1, 3", - ); - expect(stateVariables["/nocommas2"].stateValues.text).eq( - "No commas: 13", - ); - expect(stateVariables["/withcommas2"].stateValues.text).eq( - "With commas: 1, 3", - ); - }); - }); - - it("asList when copy array prop, aslist overrides", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - yes - no - maybe - - - - Override no commas: $ci.choiceTexts{asList="false"} - Copy: - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_document1")).should( - "contain.text", - "Override no commas: yes, no, maybe", - ); - cy.get(cesc2("#/_document1")).should( - "contain.text", - "Copy: yes, no, maybe", - ); - }); - - it("asList when copy array prop, test renderers", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - yes - no - maybe - - - In document: $ci.choiceTexts - $ci.choiceTexts -

$ci.choiceTexts
- $ci.choiceTexts - $ci.choiceTexts - $ci.choiceTexts - $ci.choiceTexts - $ci.choiceTexts - $ci.choiceTexts - $ci.choiceTexts - $ci.choiceTexts - A title$ci.choiceTexts - $ci.choiceTexts - -
    -
  1. $ci.choiceTexts
  2. -
-
    -
  • $ci.choiceTexts
  • -
-

$ci.choiceTexts

-
$ci.choiceTexts
-

$ci.choiceTexts

-
Title: $ci.choiceTextsText: $ci.choiceTexts
-
$ci.choiceTexts
- $ci.choiceTexts -

$ci.choiceTexts

- $ci.choiceTexts - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_document1")).should( - "contain.text", - "In document: yes, no, maybe", - ); - cy.get(cesc2("#/in_alert")).should("have.text", "yes, no, maybe"); - cy.get(cesc2("#/in_blockquote")).should("have.text", "yes, no, maybe"); - cy.get(cesc2("#/in_c")).should("have.text", "yes, no, maybe"); - cy.get(cesc2("#/in_caption")).should("have.text", "yes, no, maybe"); - cy.get(cesc2("#/in_cell")).should("have.text", "yes, no, maybe"); - cy.get(cesc2("#/in_choice")).should("have.text", "yes, no, maybe"); - cy.get(cesc2("#/in_span")).should("have.text", "yes, no, maybe"); - cy.get(cesc2("#/in_em")).should("have.text", "yes, no, maybe"); - cy.get(cesc2("#/in_feedback")).should("have.text", "yes, no, maybe"); - cy.get(cesc2("#/in_footnote")).click(); - cy.get(cesc2("#/in_footnote")).should("contain.text", "yes, no, maybe"); - cy.get(cesc2("#/in_hint_w_title")).click(); - cy.get(cesc2("#/in_hint_w_title")).should( - "contain.text", - "yes, no, maybe", - ); - cy.get(cesc2("#/in_hint_wo_title")).click(); - cy.get(cesc2("#/in_hint_wo_title")).should( - "contain.text", - "yes, no, maybe", - ); - cy.get(cesc2("#/in_label")).should("have.text", "yes, no, maybe"); - cy.get(cesc2("#/in_li")).should("have.text", "yes, no, maybe"); - cy.get(cesc2("#/in_li2")).should("have.text", "yes, no, maybe"); - cy.get(cesc2("#/in_p")).should("have.text", "yes, no, maybe"); - cy.get(cesc2("#/in_pre")).should("have.text", "yes, no, maybe"); - cy.get(cesc2("#/in_q")).should("have.text", "“yes, no, maybe”"); - cy.get(cesc2("#/in_section_w_title")).should( - "contain.text", - "Title: yes, no, maybe", - ); - cy.get(cesc2("#/in_section_w_title")).should( - "contain.text", - "Text: yes, no, maybe", - ); - cy.get(cesc2("#/in_section_wo_title")).should( - "contain.text", - "yes, no, maybe", - ); - cy.get(cesc2("#/in_solution")).click(); - cy.get(cesc2("#/in_solution")).should("contain.text", "yes, no, maybe"); - cy.get(cesc2("#/in_sq")).should("have.text", "‘yes, no, maybe’"); - cy.get(cesc2("#/in_text")).should("have.text", "yes, no, maybe"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/in_alert"].stateValues.text).eq( - "yes, no, maybe", - ); - expect(stateVariables["/in_c"].stateValues.text).eq( - "yes, no, maybe", - ); - expect(stateVariables["/in_caption"].stateValues.text).eq( - "yes, no, maybe", - ); - expect(stateVariables["/in_cell"].stateValues.text).eq( - "yes, no, maybe", - ); - expect(stateVariables["/in_choice"].stateValues.text).eq( - "yes, no, maybe", - ); - expect(stateVariables["/in_em"].stateValues.text).eq( - "yes, no, maybe", - ); - expect(stateVariables["/in_footnote"].stateValues.text).eq( - "yes, no, maybe", - ); - expect(stateVariables["/in_label"].stateValues.text).eq( - "yes, no, maybe", - ); - expect(stateVariables["/in_p"].stateValues.text).eq( - "yes, no, maybe", - ); - expect(stateVariables["/in_text"].stateValues.text).eq( - "yes, no, maybe", - ); - expect(stateVariables["/sec_title"].stateValues.text).eq( - "Title: yes, no, maybe", - ); - }); - }); - - it("copy number from external content multiple ways, change attributes", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - -

- -

- -

- -

- -

- -

- -

- -

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_p1")).should("have.text", "8.85"); - cy.get(cesc("#\\/n2")).should("have.text", "8.853729375"); - cy.get(cesc("#\\/_number1")).should("have.text", "8.85"); - cy.get(cesc("#\\/n4")).should("have.text", "8.853729375"); - cy.get(cesc("#\\/_p5")).should("have.text", "8.85"); - cy.get(cesc("#\\/n6")).should("have.text", "8.853729375"); - cy.get(cesc("#\\/_number3")).should("have.text", "8.85"); - cy.get(cesc("#\\/n8")).should("have.text", "8.853729375"); - }); - - it("correctly wrap replacement changes when verifying to force component type", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 47 - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/num")).should("have.text", "NaN"); - - cy.get(cesc("#\\/ans") + " textarea").type("4{enter}", { force: true }); - cy.get(cesc("#\\/num")).should("have.text", "4"); - - cy.get(cesc("#\\/ans") + " textarea").type("7{enter}", { force: true }); - cy.get(cesc("#\\/num")).should("have.text", "47"); - }); - - it("copy of copy with new namespace", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - hello - -

copy with new namespace:

-

copy of copy:

- -

copy of copy of copy:

-

copy of copy of copy nn:

- -

piece of copy:

-

piece of copy of copy:

- -

piece of copy of copy of copy:

-

piece of copy of copy of copy nn:

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/t")).should("have.text", "hello"); - cy.get(cesc2("#/cN/t")).should("have.text", "hello"); - cy.get(cesc2("#/cNc/t")).should("have.text", "hello"); - cy.get(cesc2("#/cNcc/t")).should("have.text", "hello"); - cy.get(cesc2("#/cNccN/t")).should("have.text", "hello"); - - cy.get(cesc2("#/cNt")).should("have.text", "hello"); - cy.get(cesc2("#/cNct")).should("have.text", "hello"); - cy.get(cesc2("#/cNcct")).should("have.text", "hello"); - cy.get(cesc2("#/cNccNt")).should("have.text", "hello"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].componentType).eq("group"); - expect(stateVariables["/t"].stateValues.value).eq("hello"); - - expect(stateVariables["/cN"].componentType).eq("group"); - expect(stateVariables["/cN/t"].stateValues.value).eq("hello"); - - expect(stateVariables["/cNc"].componentType).eq("group"); - expect(stateVariables["/cNc/t"].stateValues.value).eq("hello"); - - expect(stateVariables["/cNcc"].componentType).eq("group"); - expect(stateVariables["/cNcc/t"].stateValues.value).eq("hello"); - - expect(stateVariables["/cNccN"].componentType).eq("group"); - expect(stateVariables["/cNccN/t"].stateValues.value).eq("hello"); - }); - }); - - it("copy of copy with new namespace, macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - hello - -

copy with new namespace: $orig{name="cN" newnamespace}

-

copy of copy: $cN{name="cNc"}

- -

copy of copy of copy: $cNc{name="cNcc"}

-

copy of copy of copy nn: $cNc{name="cNccN" newNamespace}

- -

piece of copy: $(cN/t{name="cNt"})

-

piece of copy of copy: $(cNc/t{name="cNct"})

- -

piece of copy of copy of copy: $(cNcc/t{name="cNcct"})

-

piece of copy of copy of copy nn: $(cNccN/t{name="cNccNt"})

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/t")).should("have.text", "hello"); - cy.get(cesc2("#/cN/t")).should("have.text", "hello"); - cy.get(cesc2("#/cNc/t")).should("have.text", "hello"); - cy.get(cesc2("#/cNcc/t")).should("have.text", "hello"); - cy.get(cesc2("#/cNccN/t")).should("have.text", "hello"); - - cy.get(cesc2("#/cNt")).should("have.text", "hello"); - cy.get(cesc2("#/cNct")).should("have.text", "hello"); - cy.get(cesc2("#/cNcct")).should("have.text", "hello"); - cy.get(cesc2("#/cNccNt")).should("have.text", "hello"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/orig"].componentType).eq("group"); - expect(stateVariables["/t"].stateValues.value).eq("hello"); - - expect(stateVariables["/cN"].componentType).eq("group"); - expect(stateVariables["/cN/t"].stateValues.value).eq("hello"); - - expect(stateVariables["/cNc"].componentType).eq("group"); - expect(stateVariables["/cNc/t"].stateValues.value).eq("hello"); - - expect(stateVariables["/cNcc"].componentType).eq("group"); - expect(stateVariables["/cNcc/t"].stateValues.value).eq("hello"); - - expect(stateVariables["/cNccN"].componentType).eq("group"); - expect(stateVariables["/cNccN/t"].stateValues.value).eq("hello"); - }); - }); -}); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/evaluate.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/evaluate.cy.js deleted file mode 100644 index 7c55273bd..000000000 --- a/packages/test-cypress/cypress/e2e/tagSpecific/evaluate.cy.js +++ /dev/null @@ -1,9085 +0,0 @@ -import me from "math-expressions"; -import { cesc, cesc2, createFunctionFromDefinition } from "@doenet/utils"; - -describe("Evaluate Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("evaluate numeric and symbolic", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Variable:

-

Function:

-

Input value:

- - $formula - - $formula - -

Evaluate symbolic: - -

- -

Evaluate symbolic using macro: $$f_symbolic($input)

- -

Evaluated symbolic result again: $result_symbolic{name="result_symbolic3"}

- - -

Evaluate numeric: - -

- -

Evaluate numeric using macro: $$f_numeric($input)

- - -

Evaluated numeric result again: $result_numeric{name="result_numeric3"}

- - -

Force evaluate symbolic: - -

- -

Force evaluate symbolic numeric function: - -

- -

Force evaluate numeric: - -

- -

Force evaluate numeric symbolic function: - -

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.log("initial state"); - cy.get(cesc("#\\/result_symbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(0)"); - }); - cy.get(cesc("#\\/result_symbolic2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(0)"); - }); - cy.get(cesc("#\\/result_symbolic3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(0)"); - }); - cy.get(cesc("#\\/result_numeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/result_numeric2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/result_numeric3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/result_force_symbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(0)"); - }); - cy.get(cesc("#\\/result_force_symbolic_numeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(0)"); - }); - cy.get(cesc("#\\/result_force_numeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/result_force_numeric_symbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - - let result_symbolic2_name; - let result_numeric2_name; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/result_symbolic"].stateValues.value).eqls([ - "apply", - "sin", - 0, - ]); - result_symbolic2_name = - stateVariables["/result_symbolic2"].activeChildren[0] - .componentName; - expect( - stateVariables[result_symbolic2_name].stateValues.value, - ).eqls(["apply", "sin", 0]); - expect(stateVariables["/result_symbolic3"].stateValues.value).eqls([ - "apply", - "sin", - 0, - ]); - expect(stateVariables["/result_numeric"].stateValues.value).eq(0); - result_numeric2_name = - stateVariables["/result_numeric2"].activeChildren[0] - .componentName; - expect(stateVariables[result_numeric2_name].stateValues.value).eq( - 0, - ); - expect(stateVariables["/result_numeric3"].stateValues.value).eq(0); - expect( - stateVariables["/result_force_symbolic"].stateValues.value, - ).eqls(["apply", "sin", 0]); - expect( - stateVariables["/result_force_symbolic_numeric"].stateValues - .value, - ).eqls(["apply", "sin", 0]); - expect( - stateVariables["/result_force_numeric"].stateValues.value, - ).eq(0); - expect( - stateVariables["/result_force_numeric_symbolic"].stateValues - .value, - ).eq(0); - }); - - cy.log("evaluate at pi"); - cy.get(cesc("#\\/input") + " textarea").type( - "{end}{backspace}pi{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/result_symbolic")).should("contain.text", "sin(π)"); - cy.get(cesc("#\\/result_symbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π)"); - }); - cy.get(cesc("#\\/result_symbolic2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π)"); - }); - cy.get(cesc("#\\/result_symbolic3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π)"); - }); - cy.get(cesc("#\\/result_numeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("0"); - }); - cy.get(cesc("#\\/result_numeric2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("0"); - }); - cy.get(cesc("#\\/result_numeric3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("0"); - }); - cy.get(cesc("#\\/result_force_symbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π)"); - }); - cy.get(cesc("#\\/result_force_symbolic_numeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π)"); - }); - cy.get(cesc("#\\/result_force_numeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("0"); - }); - cy.get(cesc("#\\/result_force_numeric_symbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("0"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/result_symbolic"].stateValues.value).eqls([ - "apply", - "sin", - "pi", - ]); - expect( - stateVariables[result_symbolic2_name].stateValues.value, - ).eqls(["apply", "sin", "pi"]); - expect(stateVariables["/result_symbolic3"].stateValues.value).eqls([ - "apply", - "sin", - "pi", - ]); - expect(stateVariables["/result_numeric"].stateValues.value).closeTo( - 0, - 1e-10, - ); - expect( - stateVariables[result_numeric2_name].stateValues.value, - ).closeTo(0, 1e-10); - expect( - stateVariables["/result_numeric3"].stateValues.value, - ).closeTo(0, 1e-10); - expect( - stateVariables["/result_force_symbolic"].stateValues.value, - ).eqls(["apply", "sin", "pi"]); - expect( - stateVariables["/result_force_symbolic_numeric"].stateValues - .value, - ).eqls(["apply", "sin", "pi"]); - expect( - stateVariables["/result_force_numeric"].stateValues.value, - ).closeTo(0, 1e-10); - expect( - stateVariables["/result_force_numeric_symbolic"].stateValues - .value, - ).closeTo(0, 1e-10); - }); - - cy.log("change variable"); - cy.get(cesc("#\\/variable") + " textarea").type( - "{end}{backspace}y{enter}", - { force: true }, - ); - cy.get(cesc("#\\/result_symbolic")).should("contain.text", "sin(x)"); - cy.get(cesc("#\\/result_symbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(x)"); - }); - cy.get(cesc("#\\/result_symbolic2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(x)"); - }); - cy.get(cesc("#\\/result_symbolic3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(x)"); - }); - cy.get(cesc("#\\/result_numeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/result_numeric2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/result_numeric3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/result_force_symbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(x)"); - }); - cy.get(cesc("#\\/result_force_symbolic_numeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(x)"); - }); - cy.get(cesc("#\\/result_force_numeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/result_force_numeric_symbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/result_symbolic"].stateValues.value).eqls([ - "apply", - "sin", - "x", - ]); - expect( - stateVariables[result_symbolic2_name].stateValues.value, - ).eqls(["apply", "sin", "x"]); - expect(stateVariables["/result_symbolic3"].stateValues.value).eqls([ - "apply", - "sin", - "x", - ]); - assert.isNaN(stateVariables["/result_numeric"].stateValues.value); - assert.isNaN( - stateVariables[result_numeric2_name].stateValues.value, - ); - assert.isNaN(stateVariables["/result_numeric3"].stateValues.value); - expect( - stateVariables["/result_force_symbolic"].stateValues.value, - ).eqls(["apply", "sin", "x"]); - expect( - stateVariables["/result_force_symbolic_numeric"].stateValues - .value, - ).eqls(["apply", "sin", "x"]); - assert.isNaN( - stateVariables["/result_force_numeric"].stateValues.value, - ); - assert.isNaN( - stateVariables["/result_force_numeric_symbolic"].stateValues - .value, - ); - }); - - cy.log("change formula to match variable"); - cy.get(cesc("#\\/formula") + " textarea").type( - "{end}{backspace}{backspace}y{enter}", - { force: true }, - ); - cy.get(cesc("#\\/result_symbolic")).should("contain.text", "sin(π)"); - cy.get(cesc("#\\/result_symbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π)"); - }); - cy.get(cesc("#\\/result_symbolic2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π)"); - }); - cy.get(cesc("#\\/result_symbolic3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π)"); - }); - cy.get(cesc("#\\/result_numeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("0"); - }); - cy.get(cesc("#\\/result_numeric2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("0"); - }); - cy.get(cesc("#\\/result_numeric3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("0"); - }); - cy.get(cesc("#\\/result_force_symbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π)"); - }); - cy.get(cesc("#\\/result_force_symbolic_numeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π)"); - }); - cy.get(cesc("#\\/result_force_numeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("0"); - }); - cy.get(cesc("#\\/result_force_numeric_symbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("0"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/result_symbolic"].stateValues.value).eqls([ - "apply", - "sin", - "pi", - ]); - expect( - stateVariables[result_symbolic2_name].stateValues.value, - ).eqls(["apply", "sin", "pi"]); - expect(stateVariables["/result_symbolic3"].stateValues.value).eqls([ - "apply", - "sin", - "pi", - ]); - expect(stateVariables["/result_numeric"].stateValues.value).closeTo( - 0, - 1e-10, - ); - expect( - stateVariables[result_numeric2_name].stateValues.value, - ).closeTo(0, 1e-10); - expect( - stateVariables["/result_numeric3"].stateValues.value, - ).closeTo(0, 1e-10); - expect( - stateVariables["/result_force_symbolic"].stateValues.value, - ).eqls(["apply", "sin", "pi"]); - expect( - stateVariables["/result_force_symbolic_numeric"].stateValues - .value, - ).eqls(["apply", "sin", "pi"]); - expect( - stateVariables["/result_force_numeric"].stateValues.value, - ).closeTo(0, 1e-10); - expect( - stateVariables["/result_force_numeric_symbolic"].stateValues - .value, - ).closeTo(0, 1e-10); - }); - }); - - it("user-defined function", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Choose variable for function: . - Let f($x) = . - Let u = . - Then f(u) = f($u) = $$f($u).

- -

$fformula

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.log("initial state"); - - cy.get(cesc("#\\/result")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f(u)=f(3v)=3av"); - }); - - cy.log("change function"); - cy.get(cesc("#\\/fformula") + " textarea").type( - "{end}{backspace}{backspace}bx^2{enter}", - { force: true }, - ); - cy.get(cesc("#\\/result")).should("contain.text", "f(u)=f(3v)=9bv2"); - cy.get(cesc("#\\/result")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f(u)=f(3v)=9bv2"); - }); - - cy.log("change u"); - cy.get(cesc("#\\/u") + " textarea").type( - "{end}{backspace}{backspace}cq^2{enter}", - { force: true }, - ); - cy.get(cesc("#\\/result")).should("contain.text", "f(u)=f(cq2)=bc2q4"); - cy.get(cesc("#\\/result")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f(u)=f(cq2)=bc2q4"); - }); - - cy.log("change variable"); - cy.get(cesc("#\\/x") + " textarea").type("{end}{backspace}y{enter}", { - force: true, - }); - cy.get(cesc("#\\/result")).should("contain.text", "f(u)=f(cq2)=bx2"); - cy.get(cesc("#\\/result")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f(u)=f(cq2)=bx2"); - }); - - cy.log("change function to match variable"); - cy.get(cesc("#\\/fformula") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}ay+by^2{enter}", - { force: true }, - ); - cy.get(cesc("#\\/result")).should( - "contain.text", - "f(u)=f(cq2)=acq2+bc2q4", - ); - cy.get(cesc("#\\/result")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f(u)=f(cq2)=acq2+bc2q4"); - }); - }); - - it("evaluate function when input is replaced", () => { - // catch bug where child dependency was not recalculated - // when a skipComponentNames = true - // and the number of active children did not change - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 1+u - - - 1 - -

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.log("initial state"); - - cy.get(cesc("#\\/eval")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("_"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/eval"].stateValues.value).eq("_"); - }); - - cy.log("submit answer"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type("4{enter}", { - force: true, - }); - cy.get(cesc("#\\/eval")).should("contain.text", "1+4"); - cy.get(cesc("#\\/eval")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1+4"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/eval"].stateValues.value).eqls(["+", 1, 4]); - }); - }); - - it("rounding on display", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 100sin(x) - 100sin(x) - 100sin(x) - 100sin(x) - -

Input:

- -

- - - - - $ef1{name="ef1a"} - $ef2{name="ef2a"} - $ef3{name="ef3a"} - $ef4{name="ef4a"} -

- -

- - - - - $ef1dg6{name="ef1dg6a"} - $ef2dg6{name="ef2dg6a"} - $ef3dg6{name="ef3dg6a"} - $ef4dg6{name="ef4dg6a"} -

- -

- - - - - $ef1dc6{name="ef1dc6a"} - $ef2dc6{name="ef2dc6a"} - $ef3dc6{name="ef3dc6a"} - $ef4dc6{name="ef4dc6a"} -

- -

- - - - - $ef1dsz{name="ef1dsza"} - $ef2dsz{name="ef2dsza"} - $ef3dsz{name="ef3dsza"} - $ef4dsz{name="ef4dsza"} -

- -

- $$f1($input) - $$f2($input) - $$f3($input) - $$f4($input) - $ef1m{name="ef1ma"} - $ef2m{name="ef2ma"} - $ef3m{name="ef3ma"} - $ef4m{name="ef4ma"} -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/ef1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147"); - }); - cy.get(cesc("#\\/ef2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - cy.get(cesc("#\\/ef4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - cy.get(cesc("#\\/ef1a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147"); - }); - cy.get(cesc("#\\/ef2a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef3a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - cy.get(cesc("#\\/ef4a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - - cy.get(cesc("#\\/ef1dg6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef2dg6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef3dg6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef4dg6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef1dg6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef2dg6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef3dg6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef4dg6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - - cy.get(cesc("#\\/ef1dc6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef2dc6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef3dc6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef4dc6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef1dc6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef2dc6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef3dc6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef4dc6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - - cy.get(cesc("#\\/ef1dsz")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147"); - }); - cy.get(cesc("#\\/ef2dsz")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef3dsz")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - cy.get(cesc("#\\/ef4dsz")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - cy.get(cesc("#\\/ef1dsza")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147"); - }); - cy.get(cesc("#\\/ef2dsza")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef3dsza")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - cy.get(cesc("#\\/ef4dsza")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - - cy.get(cesc("#\\/ef1m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147"); - }); - cy.get(cesc("#\\/ef2m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef3m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - cy.get(cesc("#\\/ef4m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - cy.get(cesc("#\\/ef1ma")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147"); - }); - cy.get(cesc("#\\/ef2ma")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef3ma")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - cy.get(cesc("#\\/ef4ma")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - - cy.get(cesc("#\\/input") + " textarea").type( - "{end}{backspace}pi{enter}", - { - force: true, - }, - ); - - cy.get(cesc("#\\/ef2")).should("contain.text", "0"); - cy.get(cesc("#\\/ef1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 5)).eq( - Math.sin(Math.PI).toString().slice(0, 5), - ); - }); - cy.get(cesc("#\\/ef2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 3)).eq( - Math.sin(Math.PI).toString().slice(0, 3), - ); - }); - cy.get(cesc("#\\/ef1a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 5)).eq( - Math.sin(Math.PI).toString().slice(0, 5), - ); - }); - cy.get(cesc("#\\/ef2a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef3a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 3)).eq( - Math.sin(Math.PI).toString().slice(0, 3), - ); - }); - - cy.get(cesc("#\\/ef1dg6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 6)).eq( - Math.sin(Math.PI).toString().slice(0, 6), - ); - }); - cy.get(cesc("#\\/ef2dg6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 6)).eq( - Math.sin(Math.PI).toString().slice(0, 6), - ); - }); - cy.get(cesc("#\\/ef3dg6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4dg6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 6)).eq( - Math.sin(Math.PI).toString().slice(0, 6), - ); - }); - cy.get(cesc("#\\/ef1dg6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 6)).eq( - Math.sin(Math.PI).toString().slice(0, 6), - ); - }); - cy.get(cesc("#\\/ef2dg6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 6)).eq( - Math.sin(Math.PI).toString().slice(0, 6), - ); - }); - cy.get(cesc("#\\/ef3dg6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4dg6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 6)).eq( - Math.sin(Math.PI).toString().slice(0, 6), - ); - }); - - cy.get(cesc("#\\/ef1dc6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef2dc6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef3dc6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4dc6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef1dc6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef2dc6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef3dc6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4dc6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - - cy.get(cesc("#\\/ef1dsz")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef2dsz")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef3dsz")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4dsz")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef1dsza")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef2dsza")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef3dsza")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4dsza")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - - cy.get(cesc("#\\/ef1m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 6)).eq( - Math.sin(Math.PI).toString().slice(0, 6), - ); - }); - cy.get(cesc("#\\/ef2m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef3m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 3)).eq( - Math.sin(Math.PI).toString().slice(0, 3), - ); - }); - cy.get(cesc("#\\/ef1ma")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 6)).eq( - Math.sin(Math.PI).toString().slice(0, 6), - ); - }); - cy.get(cesc("#\\/ef2ma")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef3ma")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4ma")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 3)).eq( - Math.sin(Math.PI).toString().slice(0, 3), - ); - }); - }); - - it("rounding on display, overwrite on copy", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 100sin(x) - 100sin(x) - 100sin(x) - 100sin(x) - -

Input:

- -

- - - - - $ef1{name="ef1dg6" displayDigits="6"} - $ef2{name="ef2dg6" displayDigits="6"} - $ef3{name="ef3dg6" displayDigits="6"} - $ef4{name="ef4dg6" displayDigits="6"} - $ef1{name="ef1dc6" displayDecimals="6"} - $ef2{name="ef2dc6" displayDecimals="6"} - $ef3{name="ef3dc6" displayDecimals="6"} - $ef4{name="ef4dc6" displayDecimals="6"} - $ef1{name="ef1dsz" displaySmallAsZero="1E-13"} - $ef2{name="ef2dsz" displaySmallAsZero="1E-13"} - $ef3{name="ef3dsz" displaySmallAsZero="1E-13"} - $ef4{name="ef4dsz" displaySmallAsZero="1E-13"} - $ef1dc6{name="ef1dg6a" displayDigits="6"} - $ef2dc6{name="ef2dg6a" displayDigits="6"} - $ef3dc6{name="ef3dg6a" displayDigits="6"} - $ef4dc6{name="ef4dg6a" displayDigits="6"} - $ef1dg6{name="ef1dc6a" displayDecimals="6"} - $ef2dg6{name="ef2dc6a" displayDecimals="6"} - $ef3dg6{name="ef3dc6a" displayDecimals="6"} - $ef4dg6{name="ef4dc6a" displayDecimals="6"} -

- -

- - - - - $ef1dg6b{name="ef1dg8" displayDigits="8"} - $ef2dg6b{name="ef2dg8" displayDigits="8"} - $ef3dg6b{name="ef3dg8" displayDigits="8"} - $ef4dg6b{name="ef4dg8" displayDigits="8"} - $ef1dg6b{name="ef1dc6b" displayDecimals="6"} - $ef2dg6b{name="ef2dc6b" displayDecimals="6"} - $ef3dg6b{name="ef3dc6b" displayDecimals="6"} - $ef4dg6b{name="ef4dc6b" displayDecimals="6"} -

- -

- - - - - $ef1dc6c{name="ef1dc7" displayDecimals="7"} - $ef2dc6c{name="ef2dc7" displayDecimals="7"} - $ef3dc6c{name="ef3dc7" displayDecimals="7"} - $ef4dc6c{name="ef4dc7" displayDecimals="7"} - $ef1dc6c{name="ef1dg6c" displayDigits="6"} - $ef2dc6c{name="ef2dg6c" displayDigits="6"} - $ef3dc6c{name="ef3dg6c" displayDigits="6"} - $ef4dc6c{name="ef4dg6c" displayDigits="6"} -

- -

- - - - - $ef1dsza{name="ef1dsz0a" displaySmallAsZero="0"} - $ef2dsza{name="ef2dsz0a" displaySmallAsZero="0"} - $ef3dsza{name="ef3dsz0a" displaySmallAsZero="0"} - $ef4dsza{name="ef4dsz0a" displaySmallAsZero="0"} -

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/ef1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147"); - }); - cy.get(cesc("#\\/ef2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - cy.get(cesc("#\\/ef4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - - cy.get(cesc("#\\/ef1dg6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef2dg6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef3dg6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef4dg6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - - cy.get(cesc("#\\/ef1dg6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef2dg6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef3dg6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef4dg6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - - cy.get(cesc("#\\/ef1dg6b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef2dg6b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef3dg6b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef4dg6b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - - cy.get(cesc("#\\/ef1dg6c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef2dg6c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef3dg6c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef4dg6c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - - cy.get(cesc("#\\/ef1dc6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef2dc6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef3dc6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef4dc6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - - cy.get(cesc("#\\/ef1dc6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef2dc6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef3dc6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef4dc6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - - cy.get(cesc("#\\/ef1dc6b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef2dc6b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef3dc6b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef4dc6b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - - cy.get(cesc("#\\/ef1dc6c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef2dc6c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef3dc6c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef4dc6c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - - cy.get(cesc("#\\/ef1dg8")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef2dg8")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef3dg8")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef4dg8")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - - cy.get(cesc("#\\/ef1dc7")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1470985"); - }); - cy.get(cesc("#\\/ef2dc7")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1470985"); - }); - cy.get(cesc("#\\/ef3dc7")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1470985"); - }); - cy.get(cesc("#\\/ef4dc7")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1470985"); - }); - - cy.get(cesc("#\\/ef1dsz")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147"); - }); - cy.get(cesc("#\\/ef2dsz")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef3dsz")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - cy.get(cesc("#\\/ef4dsz")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - - cy.get(cesc("#\\/ef1dsza")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147"); - }); - cy.get(cesc("#\\/ef2dsza")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef3dsza")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - cy.get(cesc("#\\/ef4dsza")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - cy.get(cesc("#\\/ef1dsz0a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147"); - }); - cy.get(cesc("#\\/ef2dsz0a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef3dsz0a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - cy.get(cesc("#\\/ef4dsz0a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - - cy.get(cesc("#\\/input") + " textarea").type( - "{end}{backspace}pi{enter}", - { - force: true, - }, - ); - - cy.get(cesc("#\\/ef2")).should("contain.text", "0"); - cy.get(cesc("#\\/ef1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 6)).eq( - Math.sin(Math.PI).toString().slice(0, 6), - ); - }); - cy.get(cesc("#\\/ef2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 3)).eq( - Math.sin(Math.PI).toString().slice(0, 3), - ); - }); - - cy.get(cesc("#\\/ef1dg6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 6)).eq( - Math.sin(Math.PI).toString().slice(0, 6), - ); - }); - cy.get(cesc("#\\/ef2dg6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 6)).eq( - Math.sin(Math.PI).toString().slice(0, 6), - ); - }); - cy.get(cesc("#\\/ef3dg6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4dg6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 6)).eq( - Math.sin(Math.PI).toString().slice(0, 6), - ); - }); - - cy.get(cesc("#\\/ef1dg6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 6)).eq( - Math.sin(Math.PI).toString().slice(0, 6), - ); - }); - cy.get(cesc("#\\/ef2dg6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 6)).eq( - Math.sin(Math.PI).toString().slice(0, 6), - ); - }); - cy.get(cesc("#\\/ef3dg6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4dg6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 6)).eq( - Math.sin(Math.PI).toString().slice(0, 6), - ); - }); - - cy.get(cesc("#\\/ef1dg6b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 6)).eq( - Math.sin(Math.PI).toString().slice(0, 6), - ); - }); - cy.get(cesc("#\\/ef2dg6b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 6)).eq( - Math.sin(Math.PI).toString().slice(0, 6), - ); - }); - cy.get(cesc("#\\/ef3dg6b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4dg6b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 6)).eq( - Math.sin(Math.PI).toString().slice(0, 6), - ); - }); - - cy.get(cesc("#\\/ef1dg6c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 6)).eq( - Math.sin(Math.PI).toString().slice(0, 6), - ); - }); - cy.get(cesc("#\\/ef2dg6c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 6)).eq( - Math.sin(Math.PI).toString().slice(0, 6), - ); - }); - cy.get(cesc("#\\/ef3dg6c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4dg6c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 6)).eq( - Math.sin(Math.PI).toString().slice(0, 6), - ); - }); - - cy.get(cesc("#\\/ef1dc6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef2dc6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef3dc6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4dc6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - - cy.get(cesc("#\\/ef1dc6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef2dc6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef3dc6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4dc6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - - cy.get(cesc("#\\/ef1dc6b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef2dc6b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef3dc6b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4dc6b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - - cy.get(cesc("#\\/ef1dc6c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef2dc6c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef3dc6c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4dc6c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - - cy.get(cesc("#\\/ef1dg8")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 8)).eq( - Math.sin(Math.PI).toString().slice(0, 8), - ); - }); - cy.get(cesc("#\\/ef2dg8")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 8)).eq( - Math.sin(Math.PI).toString().slice(0, 8), - ); - }); - cy.get(cesc("#\\/ef3dg8")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4dg8")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 8)).eq( - Math.sin(Math.PI).toString().slice(0, 8), - ); - }); - - cy.get(cesc("#\\/ef1dc7")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef2dc7")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef3dc7")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4dc7")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - - cy.get(cesc("#\\/ef1dsz")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef2dsz")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef3dsz")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4dsz")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - - cy.get(cesc("#\\/ef1dsza")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef2dsza")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef3dsza")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4dsza")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - - cy.get(cesc("#\\/ef1dsz0a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 3)).eq( - Math.sin(Math.PI).toString().slice(0, 3), - ); - }); - cy.get(cesc("#\\/ef2dsz0a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef3dsz0a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 3)).eq( - Math.sin(Math.PI).toString().slice(0, 3), - ); - }); - cy.get(cesc("#\\/ef4dsz0a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 3)).eq( - Math.sin(Math.PI).toString().slice(0, 3), - ); - }); - }); - - it("rounding on display, ovewrite on copy functions", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - 100sin(x) - - -

Input:

- -

- - - - - $ef1{name="ef1a"} - $ef2{name="ef2a"} - $ef3{name="ef3a"} - $ef4{name="ef4a"} -

- -

- - - - - $ef1dg6{name="ef1dg6a"} - $ef2dg6{name="ef2dg6a"} - $ef3dg6{name="ef3dg6a"} - $ef4dg6{name="ef4dg6a"} -

- -

- - - - - $ef1dc6{name="ef1dc6a"} - $ef2dc6{name="ef2dc6a"} - $ef3dc6{name="ef3dc6a"} - $ef4dc6{name="ef4dc6a"} -

- -

- - - - - $ef1dsz{name="ef1dsza"} - $ef2dsz{name="ef2dsza"} - $ef3dsz{name="ef3dsza"} - $ef4dsz{name="ef4dsza"} -

- -

- $$f1($input) - $$f2($input) - $$f3($input) - $$f4($input) - $ef1m{name="ef1ma"} - $ef2m{name="ef2ma"} - $ef3m{name="ef3ma"} - $ef4m{name="ef4ma"} -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/ef1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147"); - }); - cy.get(cesc("#\\/ef2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - cy.get(cesc("#\\/ef4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - cy.get(cesc("#\\/ef1a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147"); - }); - cy.get(cesc("#\\/ef2a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef3a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - cy.get(cesc("#\\/ef4a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - - cy.get(cesc("#\\/ef1dg6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef2dg6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef3dg6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef4dg6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef1dg6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef2dg6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef3dg6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef4dg6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - - cy.get(cesc("#\\/ef1dc6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef2dc6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef3dc6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef4dc6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef1dc6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef2dc6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef3dc6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - cy.get(cesc("#\\/ef4dc6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147098"); - }); - - cy.get(cesc("#\\/ef1dsz")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147"); - }); - cy.get(cesc("#\\/ef2dsz")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef3dsz")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - cy.get(cesc("#\\/ef4dsz")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - cy.get(cesc("#\\/ef1dsza")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147"); - }); - cy.get(cesc("#\\/ef2dsza")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef3dsza")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - cy.get(cesc("#\\/ef4dsza")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - - cy.get(cesc("#\\/ef1m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147"); - }); - cy.get(cesc("#\\/ef2m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef3m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - cy.get(cesc("#\\/ef4m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - cy.get(cesc("#\\/ef1ma")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.147"); - }); - cy.get(cesc("#\\/ef2ma")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.1471"); - }); - cy.get(cesc("#\\/ef3ma")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - cy.get(cesc("#\\/ef4ma")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("84.15"); - }); - - cy.get(cesc("#\\/input") + " textarea").type( - "{end}{backspace}pi{enter}", - { - force: true, - }, - ); - - cy.get(cesc("#\\/ef2")).should("contain.text", "0"); - cy.get(cesc("#\\/ef1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 5)).eq( - Math.sin(Math.PI).toString().slice(0, 5), - ); - }); - cy.get(cesc("#\\/ef2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 3)).eq( - Math.sin(Math.PI).toString().slice(0, 3), - ); - }); - cy.get(cesc("#\\/ef1a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 5)).eq( - Math.sin(Math.PI).toString().slice(0, 5), - ); - }); - cy.get(cesc("#\\/ef2a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef3a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 3)).eq( - Math.sin(Math.PI).toString().slice(0, 3), - ); - }); - - cy.get(cesc("#\\/ef1dg6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 6)).eq( - Math.sin(Math.PI).toString().slice(0, 6), - ); - }); - cy.get(cesc("#\\/ef2dg6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 6)).eq( - Math.sin(Math.PI).toString().slice(0, 6), - ); - }); - cy.get(cesc("#\\/ef3dg6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4dg6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 6)).eq( - Math.sin(Math.PI).toString().slice(0, 6), - ); - }); - cy.get(cesc("#\\/ef1dg6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 6)).eq( - Math.sin(Math.PI).toString().slice(0, 6), - ); - }); - cy.get(cesc("#\\/ef2dg6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 6)).eq( - Math.sin(Math.PI).toString().slice(0, 6), - ); - }); - cy.get(cesc("#\\/ef3dg6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4dg6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 6)).eq( - Math.sin(Math.PI).toString().slice(0, 6), - ); - }); - - cy.get(cesc("#\\/ef1dc6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef2dc6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef3dc6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4dc6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef1dc6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef2dc6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef3dc6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4dc6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - - cy.get(cesc("#\\/ef1dsz")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef2dsz")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef3dsz")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4dsz")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef1dsza")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef2dsza")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef3dsza")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4dsza")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - - cy.get(cesc("#\\/ef1m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 5)).eq( - Math.sin(Math.PI).toString().slice(0, 5), - ); - }); - cy.get(cesc("#\\/ef2m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef3m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 3)).eq( - Math.sin(Math.PI).toString().slice(0, 3), - ); - }); - cy.get(cesc("#\\/ef1ma")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 5)).eq( - Math.sin(Math.PI).toString().slice(0, 5), - ); - }); - cy.get(cesc("#\\/ef2ma")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef3ma")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/ef4ma")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim().slice(0, 3)).eq( - Math.sin(Math.PI).toString().slice(0, 3), - ); - }); - }); - - it("evaluate numeric and symbolic for function of two variables", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Variable 1:

-

Variable 2:

-

Function:

-

Input 1 value:

-

Input 2 value:

- - $formula - - $formula - -

Evaluate symbolic: - -

- -

Evaluate symbolic using macro: $$f_symbolic($input1, $input2)

- -

Evaluated symbolic result again: $result_symbolic{name="result_symbolic3"}

- - -

Evaluate numeric: - -

- -

Evaluate numeric using macro: $$f_numeric($input1, $input2)

- -

Evaluated numeric result again: $result_numeric{name="result_numeric3"}

- -

Force evaluate symbolic numeric function: - -

- -

Force evaluate numeric symbolic function: - -

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.log("initial state"); - cy.get(cesc("#\\/result_symbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(0+0)"); - }); - cy.get(cesc("#\\/result_symbolic2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(0+0)"); - }); - cy.get(cesc("#\\/result_symbolic3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(0+0)"); - }); - cy.get(cesc("#\\/result_numeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/result_numeric2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/result_numeric3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/result_force_symbolic_numeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(0+0)"); - }); - cy.get(cesc("#\\/result_force_numeric_symbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - - let result_symbolic2_name; - let result_numeric2_name; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/result_symbolic"].stateValues.value).eqls([ - "apply", - "sin", - ["+", 0, 0], - ]); - result_symbolic2_name = - stateVariables["/result_symbolic2"].activeChildren[0] - .componentName; - expect( - stateVariables[result_symbolic2_name].stateValues.value, - ).eqls(["apply", "sin", ["+", 0, 0]]); - expect(stateVariables["/result_symbolic3"].stateValues.value).eqls([ - "apply", - "sin", - ["+", 0, 0], - ]); - expect(stateVariables["/result_numeric"].stateValues.value).eq(0); - result_numeric2_name = - stateVariables["/result_numeric2"].activeChildren[0] - .componentName; - expect(stateVariables[result_numeric2_name].stateValues.value).eq( - 0, - ); - expect(stateVariables["/result_numeric3"].stateValues.value).eq(0); - expect( - stateVariables["/result_force_symbolic_numeric"].stateValues - .value, - ).eqls(["apply", "sin", ["+", 0, 0]]); - expect( - stateVariables["/result_force_numeric_symbolic"].stateValues - .value, - ).eq(0); - }); - - cy.log("evaluate at (pi, 2pi)"); - cy.get(cesc("#\\/input1") + " textarea").type( - "{end}{backspace}pi{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/input2") + " textarea").type( - "{end}{backspace}2pi{enter}", - { force: true }, - ); - cy.get(cesc("#\\/result_symbolic")).should("contain.text", "sin(π+2π)"); - cy.get(cesc("#\\/result_symbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π+2π)"); - }); - cy.get(cesc("#\\/result_symbolic2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π+2π)"); - }); - cy.get(cesc("#\\/result_symbolic3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π+2π)"); - }); - cy.get(cesc("#\\/result_numeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("0"); - }); - cy.get(cesc("#\\/result_numeric2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("0"); - }); - cy.get(cesc("#\\/result_numeric3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("0"); - }); - cy.get(cesc("#\\/result_force_symbolic_numeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π+2π)"); - }); - cy.get(cesc("#\\/result_force_numeric_symbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("0"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/result_symbolic"].stateValues.value).eqls([ - "apply", - "sin", - ["+", "pi", ["*", 2, "pi"]], - ]); - expect( - stateVariables[result_symbolic2_name].stateValues.value, - ).eqls(["apply", "sin", ["+", "pi", ["*", 2, "pi"]]]); - expect(stateVariables["/result_symbolic3"].stateValues.value).eqls([ - "apply", - "sin", - ["+", "pi", ["*", 2, "pi"]], - ]); - expect(stateVariables["/result_numeric"].stateValues.value).closeTo( - 0, - 1e-10, - ); - expect( - stateVariables[result_numeric2_name].stateValues.value, - ).closeTo(0, 1e-10); - expect( - stateVariables["/result_numeric3"].stateValues.value, - ).closeTo(0, 1e-10); - expect( - stateVariables["/result_force_symbolic_numeric"].stateValues - .value, - ).eqls(["apply", "sin", ["+", "pi", ["*", 2, "pi"]]]); - expect( - stateVariables["/result_force_numeric_symbolic"].stateValues - .value, - ).closeTo(0, 1e-10); - }); - - cy.log("change variable"); - cy.get(cesc("#\\/variable1") + " textarea").type( - "{end}{backspace}u{enter}", - { force: true }, - ); - cy.get(cesc("#\\/variable2") + " textarea").type( - "{end}{backspace}v{enter}", - { force: true }, - ); - cy.get(cesc("#\\/result_symbolic")).should("contain.text", "sin(x+y)"); - cy.get(cesc("#\\/result_symbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(x+y)"); - }); - cy.get(cesc("#\\/result_symbolic2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(x+y)"); - }); - cy.get(cesc("#\\/result_symbolic3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(x+y)"); - }); - cy.get(cesc("#\\/result_numeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/result_numeric2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/result_numeric3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/result_force_symbolic_numeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(x+y)"); - }); - cy.get(cesc("#\\/result_force_numeric_symbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/result_symbolic"].stateValues.value).eqls([ - "apply", - "sin", - ["+", "x", "y"], - ]); - expect( - stateVariables[result_symbolic2_name].stateValues.value, - ).eqls(["apply", "sin", ["+", "x", "y"]]); - expect(stateVariables["/result_symbolic3"].stateValues.value).eqls([ - "apply", - "sin", - ["+", "x", "y"], - ]); - assert.isNaN(stateVariables["/result_numeric"].stateValues.value); - assert.isNaN( - stateVariables[result_numeric2_name].stateValues.value, - ); - assert.isNaN(stateVariables["/result_numeric3"].stateValues.value); - expect( - stateVariables["/result_force_symbolic_numeric"].stateValues - .value, - ).eqls(["apply", "sin", ["+", "x", "y"]]); - assert.isNaN( - stateVariables["/result_force_numeric_symbolic"].stateValues - .value, - ); - }); - - cy.log("change formula to use new variables"); - cy.get(cesc("#\\/formula") + " textarea").type( - "{end}{leftarrow}{backspace}{backspace}{backspace}u+v{enter}", - { force: true }, - ); - cy.get(cesc("#\\/result_symbolic")).should("contain.text", "sin(π+2π)"); - cy.get(cesc("#\\/result_symbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π+2π)"); - }); - cy.get(cesc("#\\/result_symbolic2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π+2π)"); - }); - cy.get(cesc("#\\/result_symbolic3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π+2π)"); - }); - cy.get(cesc("#\\/result_numeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("0"); - }); - cy.get(cesc("#\\/result_numeric2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("0"); - }); - cy.get(cesc("#\\/result_numeric3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("0"); - }); - cy.get(cesc("#\\/result_force_symbolic_numeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π+2π)"); - }); - cy.get(cesc("#\\/result_force_numeric_symbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("0"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/result_symbolic"].stateValues.value).eqls([ - "apply", - "sin", - ["+", "pi", ["*", 2, "pi"]], - ]); - expect( - stateVariables[result_symbolic2_name].stateValues.value, - ).eqls(["apply", "sin", ["+", "pi", ["*", 2, "pi"]]]); - expect(stateVariables["/result_symbolic3"].stateValues.value).eqls([ - "apply", - "sin", - ["+", "pi", ["*", 2, "pi"]], - ]); - expect(stateVariables["/result_numeric"].stateValues.value).closeTo( - 0, - 1e-10, - ); - expect( - stateVariables[result_numeric2_name].stateValues.value, - ).closeTo(0, 1e-10); - expect( - stateVariables["/result_numeric3"].stateValues.value, - ).closeTo(0, 1e-10); - expect( - stateVariables["/result_force_symbolic_numeric"].stateValues - .value, - ).eqls(["apply", "sin", ["+", "pi", ["*", 2, "pi"]]]); - expect( - stateVariables["/result_force_numeric_symbolic"].stateValues - .value, - ).closeTo(0, 1e-10); - }); - }); - - it("function of multiple variables", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Variables:

-

Function:

-

Input:

- $variablesOrig - - $formula - -

Evaluate 1: - -

- -

Evaluate 2: $$f($input)

- -

Evaluate 3: $result1{name="result3"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.log("initial state"); - cy.get(cesc("#\\/result1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/result2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/result3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - let result2Name; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/result1"].stateValues.value).eqls(0); - result2Name = - stateVariables["/result2"].activeChildren[0].componentName; - expect(stateVariables[result2Name].stateValues.value).eqls(0); - expect(stateVariables["/result3"].stateValues.value).eqls(0); - }); - - cy.log("evaluate at (pi, pi/2)"); - cy.get(cesc("#\\/input") + " textarea").type( - "{end}{leftArrow}{backspace}{backspace}{backspace}pi,pi/2{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/result1")).should("contain.text", "−1"); - cy.get(cesc("#\\/result1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−1"); - }); - cy.get(cesc("#\\/result2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−1"); - }); - cy.get(cesc("#\\/result3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−1"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/result1"].stateValues.value).eqls(-1); - expect(stateVariables[result2Name].stateValues.value).eqls(-1); - expect(stateVariables["/result3"].stateValues.value).eqls(-1); - }); - - cy.log("change variables to 3D"); - cy.get(cesc("#\\/variablesOrig") + " textarea").type("{end},z{enter}", { - force: true, - }); - - cy.get(cesc("#\\/result1")).should("contain.text", "_"); - cy.get(cesc("#\\/result1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("_"); - }); - cy.get(cesc("#\\/result2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("_"); - }); - cy.get(cesc("#\\/result3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("_"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/result1"].stateValues.value).eqls("_"); - expect(stateVariables[result2Name].stateValues.value).eqls("_"); - expect(stateVariables["/result3"].stateValues.value).eqls("_"); - }); - - cy.log("change input to 3D"); - cy.get(cesc("#\\/input") + " textarea").type( - "{end}{leftArrow},3{enter}", - { - force: true, - }, - ); - - cy.get(cesc("#\\/result1")).should("contain.text", "−1"); - cy.get(cesc("#\\/result1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−1"); - }); - cy.get(cesc("#\\/result2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−1"); - }); - cy.get(cesc("#\\/result3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−1"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/result1"].stateValues.value).eqls(-1); - expect(stateVariables[result2Name].stateValues.value).eqls(-1); - expect(stateVariables["/result3"].stateValues.value).eqls(-1); - }); - - cy.log("change formula to use all variables"); - cy.get(cesc("#\\/formula") + " textarea").type("z{enter}", { - force: true, - }); - - cy.get(cesc("#\\/result1")).should("contain.text", "−3"); - cy.get(cesc("#\\/result1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−3"); - }); - cy.get(cesc("#\\/result2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−3"); - }); - cy.get(cesc("#\\/result3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−3"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/result1"].stateValues.value).eqls(-3); - expect(stateVariables[result2Name].stateValues.value).eqls(-3); - expect(stateVariables["/result3"].stateValues.value).eqls(-3); - }); - - cy.log("add fourth variable to formula"); - cy.get(cesc("#\\/formula") + " textarea").type( - "{end}{leftArrow}/w{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/result1")).should("contain.text", "3sin(π+π2w)"); - cy.get(cesc("#\\/result1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3sin(π+π2w)"); - }); - cy.get(cesc("#\\/result2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3sin(π+π2w)"); - }); - cy.get(cesc("#\\/result3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3sin(π+π2w)"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/result1"].stateValues.value).eqls([ - "*", - 3, - ["apply", "sin", ["+", "pi", ["/", "pi", ["*", 2, "w"]]]], - ]); - expect(stateVariables[result2Name].stateValues.value).eqls([ - "*", - 3, - ["apply", "sin", ["+", "pi", ["/", "pi", ["*", 2, "w"]]]], - ]); - expect(stateVariables["/result3"].stateValues.value).eqls([ - "*", - 3, - ["apply", "sin", ["+", "pi", ["/", "pi", ["*", 2, "w"]]]], - ]); - }); - - cy.log("add 4th input"); - cy.get(cesc("#\\/input") + " textarea").type( - "{end}{leftArrow},3{enter}", - { - force: true, - }, - ); - - cy.get(cesc("#\\/result1")).should("contain.text", "_"); - cy.get(cesc("#\\/result1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("_"); - }); - cy.get(cesc("#\\/result2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("_"); - }); - cy.get(cesc("#\\/result3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("_"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/result1"].stateValues.value).eqls("_"); - expect(stateVariables[result2Name].stateValues.value).eqls("_"); - expect(stateVariables["/result3"].stateValues.value).eqls("_"); - }); - - cy.log("add 4th variable"); - cy.get(cesc("#\\/variablesOrig") + " textarea").type("{end},w{enter}", { - force: true, - }); - - cy.get(cesc("#\\/result1")).should("contain.text", "−32"); - cy.get(cesc("#\\/result1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−32"); - }); - cy.get(cesc("#\\/result2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−32"); - }); - cy.get(cesc("#\\/result3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−32"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/result1"].stateValues.value).eqls([ - "/", - -3, - 2, - ]); - expect(stateVariables[result2Name].stateValues.value).eqls([ - "/", - -3, - 2, - ]); - expect(stateVariables["/result3"].stateValues.value).eqls([ - "/", - -3, - 2, - ]); - }); - }); - - it("different input forms for function of two variables", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x^2/y^3 -

Input as vector:

-

Input as list:

- $input2Orig - - - - - - - -

Separate inputs: -

- - -

Evaluate 1a: - -

-

Evaluate 1b: $$f($input1)

- -

Evaluate 2a: - -

-

Evaluate 2b: $$f($input2)

- -

Evaluate 3a: - -

-

Evaluate 3b: $$f($input3)

- -

Evaluate 4a: - -

-

Evaluate 4b: $$f($input4a,$input4b)

-

Evaluate 4c: $$f($input4a, $input4b)

- -

Evaluate 5a: - -

-

Evaluate 5b: $$f(($input4a,$input4b))

-

Evaluate 5c: $$f(($input4a, $input4b))

-

Evaluate 5d: - -

- -

Evaluate 6a: - -

-

Evaluate 6b: $$f(2,3)

-

Evaluate 6c: $$f(2, 3)

- -

Evaluate 7a: - -

-

Evaluate 7b: $$f((2,3))

-

Evaluate 7c: $$f((2, 3))

-

Evaluate 7d: - -

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.log("initial state"); - cy.get(cesc("#\\/result1a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("427"); - }); - cy.get(cesc("#\\/result1b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("427"); - }); - cy.get(cesc("#\\/result2a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("427"); - }); - cy.get(cesc("#\\/result2b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("427"); - }); - cy.get(cesc("#\\/result3a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("427"); - }); - cy.get(cesc("#\\/result3b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("427"); - }); - cy.get(cesc("#\\/result4a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("427"); - }); - cy.get(cesc("#\\/result4b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("427"); - }); - cy.get(cesc("#\\/result4c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("427"); - }); - cy.get(cesc("#\\/result5a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("427"); - }); - cy.get(cesc("#\\/result5b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("427"); - }); - cy.get(cesc("#\\/result5c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("427"); - }); - cy.get(cesc("#\\/result5d")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("427"); - }); - cy.get(cesc("#\\/result6a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("427"); - }); - cy.get(cesc("#\\/result6b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("427"); - }); - cy.get(cesc("#\\/result6c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("427"); - }); - cy.get(cesc("#\\/result7a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("427"); - }); - cy.get(cesc("#\\/result7a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("427"); - }); - cy.get(cesc("#\\/result7c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("427"); - }); - cy.get(cesc("#\\/result7d")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("427"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/result1a"].stateValues.value).eqls([ - "/", - 4, - 27, - ]); - expect( - stateVariables[ - stateVariables["/result1b"].activeChildren[0].componentName - ].stateValues.value, - ).eqls(["/", 4, 27]); - expect(stateVariables["/result2a"].stateValues.value).eqls([ - "/", - 4, - 27, - ]); - expect( - stateVariables[ - stateVariables["/result2b"].activeChildren[0].componentName - ].stateValues.value, - ).eqls(["/", 4, 27]); - expect(stateVariables["/result3a"].stateValues.value).eqls([ - "/", - 4, - 27, - ]); - expect( - stateVariables[ - stateVariables["/result3b"].activeChildren[0].componentName - ].stateValues.value, - ).eqls(["/", 4, 27]); - expect(stateVariables["/result4a"].stateValues.value).eqls([ - "/", - 4, - 27, - ]); - expect( - stateVariables[ - stateVariables["/result4b"].activeChildren[0].componentName - ].stateValues.value, - ).eqls(["/", 4, 27]); - expect( - stateVariables[ - stateVariables["/result4c"].activeChildren[0].componentName - ].stateValues.value, - ).eqls(["/", 4, 27]); - expect(stateVariables["/result5a"].stateValues.value).eqls([ - "/", - 4, - 27, - ]); - expect( - stateVariables[ - stateVariables["/result5b"].activeChildren[0].componentName - ].stateValues.value, - ).eqls(["/", 4, 27]); - expect( - stateVariables[ - stateVariables["/result5c"].activeChildren[0].componentName - ].stateValues.value, - ).eqls(["/", 4, 27]); - expect(stateVariables["/result5d"].stateValues.value).eqls([ - "/", - 4, - 27, - ]); - expect(stateVariables["/result6a"].stateValues.value).eqls([ - "/", - 4, - 27, - ]); - expect( - stateVariables[ - stateVariables["/result6b"].activeChildren[0].componentName - ].stateValues.value, - ).eqls(["/", 4, 27]); - expect( - stateVariables[ - stateVariables["/result6c"].activeChildren[0].componentName - ].stateValues.value, - ).eqls(["/", 4, 27]); - expect(stateVariables["/result7a"].stateValues.value).eqls([ - "/", - 4, - 27, - ]); - expect( - stateVariables[ - stateVariables["/result7b"].activeChildren[0].componentName - ].stateValues.value, - ).eqls(["/", 4, 27]); - expect( - stateVariables[ - stateVariables["/result7c"].activeChildren[0].componentName - ].stateValues.value, - ).eqls(["/", 4, 27]); - expect(stateVariables["/result7d"].stateValues.value).eqls([ - "/", - 4, - 27, - ]); - }); - - cy.log(`change inputs, use altvector`); - cy.get(cesc("#\\/input1") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}\\langle -3,5\\rangle{enter}", - { force: true }, - ); - cy.get(cesc("#\\/input2Orig") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}-3,5", - { force: true }, - ); - cy.get(cesc("#\\/input4a") + " textarea").type("{end}{backspace}-3", { - force: true, - }); - cy.get(cesc("#\\/input4b") + " textarea") - .type("{end}{backspace}5", { force: true }) - .blur(); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/A", - args: { x: -3, y: 7 }, - }); - await win.callAction1({ - actionName: "movePoint", - componentName: "/B", - args: { x: 5, y: -9 }, - }); - - cy.get(cesc("#\\/result1a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9125"); - }); - cy.get(cesc("#\\/result1b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9125"); - }); - cy.get(cesc("#\\/result2a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9125"); - }); - cy.get(cesc("#\\/result2b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9125"); - }); - cy.get(cesc("#\\/result3a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9125"); - }); - cy.get(cesc("#\\/result3b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9125"); - }); - cy.get(cesc("#\\/result4a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9125"); - }); - cy.get(cesc("#\\/result4b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9125"); - }); - cy.get(cesc("#\\/result4c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9125"); - }); - cy.get(cesc("#\\/result5a")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9125"); - }); - cy.get(cesc("#\\/result5b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9125"); - }); - cy.get(cesc("#\\/result5c")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9125"); - }); - cy.get(cesc("#\\/result5d")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9125"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/result1a"].stateValues.value).eqls([ - "/", - 9, - 125, - ]); - expect( - stateVariables[ - stateVariables["/result1b"].activeChildren[0] - .componentName - ].stateValues.value, - ).eqls(["/", 9, 125]); - expect(stateVariables["/result2a"].stateValues.value).eqls([ - "/", - 9, - 125, - ]); - expect( - stateVariables[ - stateVariables["/result2b"].activeChildren[0] - .componentName - ].stateValues.value, - ).eqls(["/", 9, 125]); - expect(stateVariables["/result3a"].stateValues.value).eqls([ - "/", - 9, - 125, - ]); - expect( - stateVariables[ - stateVariables["/result3b"].activeChildren[0] - .componentName - ].stateValues.value, - ).eqls(["/", 9, 125]); - expect(stateVariables["/result4a"].stateValues.value).eqls([ - "/", - 9, - 125, - ]); - expect( - stateVariables[ - stateVariables["/result4b"].activeChildren[0] - .componentName - ].stateValues.value, - ).eqls(["/", 9, 125]); - expect( - stateVariables[ - stateVariables["/result4c"].activeChildren[0] - .componentName - ].stateValues.value, - ).eqls(["/", 9, 125]); - expect(stateVariables["/result5a"].stateValues.value).eqls([ - "/", - 9, - 125, - ]); - expect( - stateVariables[ - stateVariables["/result5b"].activeChildren[0] - .componentName - ].stateValues.value, - ).eqls(["/", 9, 125]); - expect( - stateVariables[ - stateVariables["/result5c"].activeChildren[0] - .componentName - ].stateValues.value, - ).eqls(["/", 9, 125]); - expect(stateVariables["/result5d"].stateValues.value).eqls([ - "/", - 9, - 125, - ]); - }); - }); - }); - - it("evaluate numeric and symbolic for vector-valued function of two variables", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Variable 1:

-

Variable 2:

-

Function:

-

Input 1 value:

-

Input 2 value:

- - $formula - - $formula - -

Evaluate symbolic: - -

- -

Evaluate symbolic using macro: $$f_symbolic($input1, $input2)

- -

Evaluated symbolic result again: $result_symbolic{name="result_symbolic3"}

- - -

Evaluate numeric: - -

- -

Evaluate numeric using macro: $$f_numeric($input1, $input2)

- -

Evaluated numeric result again: $result_numeric{name="result_numeric3"}

- -

Force evaluate symbolic numeric function: - -

- -

Force evaluate numeric symbolic function: - -

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.log("initial state"); - cy.get(cesc("#\\/result_symbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(sin(0),cos(0))"); - }); - cy.get(cesc("#\\/result_symbolic2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(sin(0),cos(0))"); - }); - cy.get(cesc("#\\/result_symbolic3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(sin(0),cos(0))"); - }); - cy.get(cesc("#\\/result_numeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,1)"); - }); - cy.get(cesc("#\\/result_numeric2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,1)"); - }); - cy.get(cesc("#\\/result_numeric3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,1)"); - }); - cy.get(cesc("#\\/result_force_symbolic_numeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(sin(0),cos(0))"); - }); - cy.get(cesc("#\\/result_force_numeric_symbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,1)"); - }); - - let result_symbolic2_name; - let result_numeric2_name; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/result_symbolic"].stateValues.value).eqls([ - "vector", - ["apply", "sin", 0], - ["apply", "cos", 0], - ]); - result_symbolic2_name = - stateVariables["/result_symbolic2"].activeChildren[0] - .componentName; - expect( - stateVariables[result_symbolic2_name].stateValues.value, - ).eqls(["vector", ["apply", "sin", 0], ["apply", "cos", 0]]); - expect(stateVariables["/result_symbolic3"].stateValues.value).eqls([ - "vector", - ["apply", "sin", 0], - ["apply", "cos", 0], - ]); - expect(stateVariables["/result_numeric"].stateValues.value).eqls([ - "vector", - 0, - 1, - ]); - result_numeric2_name = - stateVariables["/result_numeric2"].activeChildren[0] - .componentName; - expect(stateVariables[result_numeric2_name].stateValues.value).eqls( - ["vector", 0, 1], - ); - expect(stateVariables["/result_numeric3"].stateValues.value).eqls([ - "vector", - 0, - 1, - ]); - expect( - stateVariables["/result_force_symbolic_numeric"].stateValues - .value, - ).eqls(["vector", ["apply", "sin", 0], ["apply", "cos", 0]]); - expect( - stateVariables["/result_force_numeric_symbolic"].stateValues - .value, - ).eqls(["vector", 0, 1]); - }); - - cy.log("evaluate at (pi, 2pi)"); - cy.get(cesc("#\\/input1") + " textarea").type( - "{end}{backspace}pi{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/input2") + " textarea").type( - "{end}{backspace}2pi{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/result_symbolic")).should( - "contain.text", - "(sin(π+2π),cos(π−2π))", - ); - cy.get(cesc("#\\/result_symbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(sin(π+2π),cos(π−2π))"); - }); - cy.get(cesc("#\\/result_symbolic2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(sin(π+2π),cos(π−2π))"); - }); - cy.get(cesc("#\\/result_symbolic3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(sin(π+2π),cos(π−2π))"); - }); - cy.get(cesc("#\\/result_numeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,−1)"); - }); - cy.get(cesc("#\\/result_numeric2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,−1)"); - }); - cy.get(cesc("#\\/result_numeric3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,−1)"); - }); - cy.get(cesc("#\\/result_force_symbolic_numeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(sin(π+2π),cos(π−2π))"); - }); - cy.get(cesc("#\\/result_force_numeric_symbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,−1)"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/result_symbolic"].stateValues.value).eqls([ - "vector", - ["apply", "sin", ["+", "pi", ["*", 2, "pi"]]], - ["apply", "cos", ["+", "pi", ["*", -2, "pi"]]], - ]); - expect( - stateVariables[result_symbolic2_name].stateValues.value, - ).eqls([ - "vector", - ["apply", "sin", ["+", "pi", ["*", 2, "pi"]]], - ["apply", "cos", ["+", "pi", ["*", -2, "pi"]]], - ]); - expect(stateVariables["/result_symbolic3"].stateValues.value).eqls([ - "vector", - ["apply", "sin", ["+", "pi", ["*", 2, "pi"]]], - ["apply", "cos", ["+", "pi", ["*", -2, "pi"]]], - ]); - expect( - stateVariables["/result_numeric"].stateValues.value.map((x) => - typeof x === "number" && me.math.round(x, 10) === 0 ? 0 : x, - ), - ).eqls(["vector", 0, -1]); - expect( - stateVariables[result_numeric2_name].stateValues.value.map( - (x) => - typeof x === "number" && me.math.round(x, 10) === 0 - ? 0 - : x, - ), - ).eqls(["vector", 0, -1]); - expect( - stateVariables["/result_numeric3"].stateValues.value.map((x) => - typeof x === "number" && me.math.round(x, 10) === 0 ? 0 : x, - ), - ).eqls(["vector", 0, -1]); - expect( - stateVariables["/result_force_symbolic_numeric"].stateValues - .value, - ).eqls([ - "vector", - ["apply", "sin", ["+", "pi", ["*", 2, "pi"]]], - ["apply", "cos", ["+", "pi", ["*", -2, "pi"]]], - ]); - expect( - stateVariables[ - "/result_force_numeric_symbolic" - ].stateValues.value.map((x) => - typeof x === "number" && me.math.round(x, 10) === 0 ? 0 : x, - ), - ).eqls(["vector", 0, -1]); - }); - - cy.log("change variable"); - cy.get(cesc("#\\/variable1") + " textarea").type( - "{end}{backspace}u{enter}", - { force: true }, - ); - cy.get(cesc("#\\/variable2") + " textarea").type( - "{end}{backspace}v{enter}", - { force: true }, - ); - cy.get(cesc("#\\/result_symbolic")).should( - "contain.text", - "(sin(x+y),cos(x−y))", - ); - cy.get(cesc("#\\/result_symbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(sin(x+y),cos(x−y))"); - }); - cy.get(cesc("#\\/result_symbolic2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(sin(x+y),cos(x−y))"); - }); - cy.get(cesc("#\\/result_symbolic3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(sin(x+y),cos(x−y))"); - }); - cy.get(cesc("#\\/result_numeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(NaN,NaN)"); - }); - cy.get(cesc("#\\/result_numeric2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(NaN,NaN)"); - }); - cy.get(cesc("#\\/result_numeric3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(NaN,NaN)"); - }); - cy.get(cesc("#\\/result_force_symbolic_numeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(sin(x+y),cos(x−y))"); - }); - cy.get(cesc("#\\/result_force_numeric_symbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(NaN,NaN)"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/result_symbolic"].stateValues.value).eqls([ - "vector", - ["apply", "sin", ["+", "x", "y"]], - ["apply", "cos", ["+", "x", ["-", "y"]]], - ]); - expect( - stateVariables[result_symbolic2_name].stateValues.value, - ).eqls([ - "vector", - ["apply", "sin", ["+", "x", "y"]], - ["apply", "cos", ["+", "x", ["-", "y"]]], - ]); - expect(stateVariables["/result_symbolic3"].stateValues.value).eqls([ - "vector", - ["apply", "sin", ["+", "x", "y"]], - ["apply", "cos", ["+", "x", ["-", "y"]]], - ]); - assert.isNaN( - stateVariables["/result_numeric"].stateValues.value[1], - ); - assert.isNaN( - stateVariables["/result_numeric"].stateValues.value[2], - ); - assert.isNaN( - stateVariables[result_numeric2_name].stateValues.value[1], - ); - assert.isNaN( - stateVariables[result_numeric2_name].stateValues.value[2], - ); - assert.isNaN( - stateVariables["/result_numeric3"].stateValues.value[1], - ); - assert.isNaN( - stateVariables["/result_numeric3"].stateValues.value[2], - ); - expect( - stateVariables["/result_force_symbolic_numeric"].stateValues - .value, - ).eqls([ - "vector", - ["apply", "sin", ["+", "x", "y"]], - ["apply", "cos", ["+", "x", ["-", "y"]]], - ]); - assert.isNaN( - stateVariables["/result_force_numeric_symbolic"].stateValues - .value[1], - ); - assert.isNaN( - stateVariables["/result_force_numeric_symbolic"].stateValues - .value[2], - ); - }); - - cy.log("change formula to use new variables"); - cy.get(cesc("#\\/formula") + " textarea").type( - "{end}{leftArrow}{leftArrow}{backspace}{backspace}{backspace}u-v{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{leftArrow}{backspace}{backspace}{backspace}u+v{enter}", - { force: true }, - ); - cy.get(cesc("#\\/result_symbolic")).should( - "contain.text", - "(sin(π+2π),cos(π−2π))", - ); - - cy.get(cesc("#\\/result_symbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(sin(π+2π),cos(π−2π))"); - }); - cy.get(cesc("#\\/result_symbolic2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(sin(π+2π),cos(π−2π))"); - }); - cy.get(cesc("#\\/result_symbolic3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(sin(π+2π),cos(π−2π))"); - }); - cy.get(cesc("#\\/result_numeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,−1)"); - }); - cy.get(cesc("#\\/result_numeric2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,−1)"); - }); - cy.get(cesc("#\\/result_numeric3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,−1)"); - }); - cy.get(cesc("#\\/result_force_symbolic_numeric")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(sin(π+2π),cos(π−2π))"); - }); - cy.get(cesc("#\\/result_force_numeric_symbolic")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,−1)"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/result_symbolic"].stateValues.value).eqls([ - "vector", - ["apply", "sin", ["+", "pi", ["*", 2, "pi"]]], - ["apply", "cos", ["+", "pi", ["*", -2, "pi"]]], - ]); - expect( - stateVariables[result_symbolic2_name].stateValues.value, - ).eqls([ - "vector", - ["apply", "sin", ["+", "pi", ["*", 2, "pi"]]], - ["apply", "cos", ["+", "pi", ["*", -2, "pi"]]], - ]); - expect(stateVariables["/result_symbolic3"].stateValues.value).eqls([ - "vector", - ["apply", "sin", ["+", "pi", ["*", 2, "pi"]]], - ["apply", "cos", ["+", "pi", ["*", -2, "pi"]]], - ]); - expect( - stateVariables["/result_numeric"].stateValues.value.map((x) => - typeof x === "number" && me.math.round(x, 10) === 0 ? 0 : x, - ), - ).eqls(["vector", 0, -1]); - expect( - stateVariables[result_numeric2_name].stateValues.value.map( - (x) => - typeof x === "number" && me.math.round(x, 10) === 0 - ? 0 - : x, - ), - ).eqls(["vector", 0, -1]); - expect( - stateVariables["/result_numeric3"].stateValues.value.map((x) => - typeof x === "number" && me.math.round(x, 10) === 0 ? 0 : x, - ), - ).eqls(["vector", 0, -1]); - expect( - stateVariables["/result_force_symbolic_numeric"].stateValues - .value, - ).eqls([ - "vector", - ["apply", "sin", ["+", "pi", ["*", 2, "pi"]]], - ["apply", "cos", ["+", "pi", ["*", -2, "pi"]]], - ]); - expect( - stateVariables[ - "/result_force_numeric_symbolic" - ].stateValues.value.map((x) => - typeof x === "number" && me.math.round(x, 10) === 0 ? 0 : x, - ), - ).eqls(["vector", 0, -1]); - }); - }); - - it("vector-valued function of multiple variables", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Variables:

-

Function:

-

Input:

- $variablesOrig - - $formula - -

Evaluate 1: - -

- -

Evaluate 2: $$f($input)

- -

Evaluate 3: $result1{name="result3"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.log("initial state"); - cy.get(cesc("#\\/result1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,0)"); - }); - cy.get(cesc("#\\/result2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,0)"); - }); - cy.get(cesc("#\\/result3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,0)"); - }); - let result2Name; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/f"].stateValues.numInputs).eq(2); - expect(stateVariables["/f"].stateValues.numOutputs).eq(2); - expect(stateVariables["/result1"].stateValues.value).eqls([ - "vector", - 0, - 0, - ]); - result2Name = - stateVariables["/result2"].activeChildren[0].componentName; - expect(stateVariables[result2Name].stateValues.value).eqls([ - "vector", - 0, - 0, - ]); - expect(stateVariables["/result3"].stateValues.value).eqls([ - "vector", - 0, - 0, - ]); - }); - - cy.log("evaluate at (7,3)"); - cy.get(cesc("#\\/input") + " textarea").type( - "{end}{leftArrow}{backspace}{backspace}{backspace}7,3{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/result1")).should("contain.text", "(10,4)"); - cy.get(cesc("#\\/result1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(10,4)"); - }); - cy.get(cesc("#\\/result2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(10,4)"); - }); - cy.get(cesc("#\\/result3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(10,4)"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/f"].stateValues.numInputs).eq(2); - expect(stateVariables["/f"].stateValues.numOutputs).eq(2); - expect(stateVariables["/result1"].stateValues.value).eqls([ - "vector", - 10, - 4, - ]); - expect(stateVariables[result2Name].stateValues.value).eqls([ - "vector", - 10, - 4, - ]); - expect(stateVariables["/result3"].stateValues.value).eqls([ - "vector", - 10, - 4, - ]); - }); - - cy.log("change variables to 3D"); - cy.get(cesc("#\\/variablesOrig") + " textarea").type("{end},z{enter}", { - force: true, - }); - - cy.get(cesc("#\\/result1")).should("contain.text", "_"); - cy.get(cesc("#\\/result1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("_"); - }); - cy.get(cesc("#\\/result2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("_"); - }); - cy.get(cesc("#\\/result3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("_"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/f"].stateValues.numInputs).eq(3); - expect(stateVariables["/f"].stateValues.numOutputs).eq(2); - expect(stateVariables["/result1"].stateValues.value).eqls("_"); - expect(stateVariables[result2Name].stateValues.value).eqls("_"); - expect(stateVariables["/result3"].stateValues.value).eqls("_"); - }); - - cy.log("change input to 3D"); - cy.get(cesc("#\\/input") + " textarea").type( - "{end}{leftArrow},2{enter}", - { - force: true, - }, - ); - - cy.get(cesc("#\\/result1")).should("contain.text", "(10,4)"); - cy.get(cesc("#\\/result1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(10,4)"); - }); - cy.get(cesc("#\\/result2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(10,4)"); - }); - cy.get(cesc("#\\/result3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(10,4)"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/f"].stateValues.numInputs).eq(3); - expect(stateVariables["/f"].stateValues.numOutputs).eq(2); - expect(stateVariables["/result1"].stateValues.value).eqls([ - "vector", - 10, - 4, - ]); - expect(stateVariables[result2Name].stateValues.value).eqls([ - "vector", - 10, - 4, - ]); - expect(stateVariables["/result3"].stateValues.value).eqls([ - "vector", - 10, - 4, - ]); - }); - - cy.log("change formula to use all variables"); - cy.get(cesc("#\\/formula") + " textarea").type( - "{rightArrow}z{end}{leftArrow}z{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/result1")).should("contain.text", "(17,1)"); - cy.get(cesc("#\\/result1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(17,1)"); - }); - cy.get(cesc("#\\/result2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(17,1)"); - }); - cy.get(cesc("#\\/result3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(17,1)"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/f"].stateValues.numInputs).eq(3); - expect(stateVariables["/f"].stateValues.numOutputs).eq(2); - expect(stateVariables["/result1"].stateValues.value).eqls([ - "vector", - 17, - 1, - ]); - expect(stateVariables[result2Name].stateValues.value).eqls([ - "vector", - 17, - 1, - ]); - expect(stateVariables["/result3"].stateValues.value).eqls([ - "vector", - 17, - 1, - ]); - }); - - cy.log("add third dimension"); - cy.get(cesc("#\\/formula") + " textarea").type("{end},xyz{enter}", { - force: true, - }); - - cy.get(cesc("#\\/result1")).should("contain.text", "(17,1,42)"); - cy.get(cesc("#\\/result1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(17,1,42)"); - }); - cy.get(cesc("#\\/result2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(17,1,42)"); - }); - cy.get(cesc("#\\/result3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(17,1,42)"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/f"].stateValues.numInputs).eq(3); - expect(stateVariables["/f"].stateValues.numOutputs).eq(3); - expect(stateVariables["/result1"].stateValues.value).eqls([ - "vector", - 17, - 1, - 42, - ]); - expect(stateVariables[result2Name].stateValues.value).eqls([ - "vector", - 17, - 1, - 42, - ]); - expect(stateVariables["/result3"].stateValues.value).eqls([ - "vector", - 17, - 1, - 42, - ]); - }); - - cy.log("add fourth variable and 4th dimension to formula"); - cy.get(cesc("#\\/formula") + " textarea").type("{end}w,w{enter}", { - force: true, - }); - - cy.get(cesc("#\\/result1")).should("contain.text", "(17,1,42w,w)"); - cy.get(cesc("#\\/result1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(17,1,42w,w)"); - }); - cy.get(cesc("#\\/result2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(17,1,42w,w)"); - }); - cy.get(cesc("#\\/result3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(17,1,42w,w)"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/f"].stateValues.numInputs).eq(3); - expect(stateVariables["/f"].stateValues.numOutputs).eq(4); - expect(stateVariables["/result1"].stateValues.value).eqls([ - "vector", - 17, - 1, - ["*", 42, "w"], - "w", - ]); - expect(stateVariables[result2Name].stateValues.value).eqls([ - "vector", - 17, - 1, - ["*", 42, "w"], - "w", - ]); - expect(stateVariables["/result3"].stateValues.value).eqls([ - "vector", - 17, - 1, - ["*", 42, "w"], - "w", - ]); - }); - - cy.log("add 4th input"); - cy.get(cesc("#\\/input") + " textarea").type( - "{end}{leftArrow},5{enter}", - { - force: true, - }, - ); - - cy.get(cesc("#\\/result1")).should("contain.text", "_"); - cy.get(cesc("#\\/result1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("_"); - }); - cy.get(cesc("#\\/result2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("_"); - }); - cy.get(cesc("#\\/result3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("_"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/result1"].stateValues.value).eqls("_"); - expect(stateVariables[result2Name].stateValues.value).eqls("_"); - expect(stateVariables["/result3"].stateValues.value).eqls("_"); - }); - - cy.log("add 4th variable"); - cy.get(cesc("#\\/variablesOrig") + " textarea").type("{end},w{enter}", { - force: true, - }); - - cy.get(cesc("#\\/result1")).should("contain.text", "(17,1,210,5)"); - cy.get(cesc("#\\/result1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(17,1,210,5)"); - }); - cy.get(cesc("#\\/result2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(17,1,210,5)"); - }); - cy.get(cesc("#\\/result3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(17,1,210,5)"); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/result1"].stateValues.value).eqls([ - "vector", - 17, - 1, - 210, - 5, - ]); - expect(stateVariables[result2Name].stateValues.value).eqls([ - "vector", - 17, - 1, - 210, - 5, - ]); - expect(stateVariables["/result3"].stateValues.value).eqls([ - "vector", - 17, - 1, - 210, - 5, - ]); - }); - }); - - it("change variables of symbolic function", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

f: st^2

-

g: $f.formula

- -

f(u, v+w) = $$f(u, v+w)

-

f(a+b, c) = $$f(a+b, c)

-

g(u, v+w) = $$g(u, v+w)

-

g(a+b, c) = $$g(a+b, c)

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.log("initial state"); - - cy.get(cesc("#\\/pf1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("uv2+2uvw+uw2"); - }); - cy.get(cesc("#\\/pf2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("ac2+bc2"); - }); - cy.get(cesc("#\\/pg1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("vu2+wu2"); - }); - cy.get(cesc("#\\/pg2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("ca2+2abc+cb2"); - }); - }); - - it("change variables of numeric function", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

f: st^2

-

g: $f.formula

- -

f(2, -3) = $$f(2, -3)

-

g(2, -3) = $$g(2, -3)

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.log("initial state"); - - cy.get(cesc("#\\/pf")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("18"); - }); - cy.get(cesc("#\\/pg")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−12"); - }); - }); - - it("change variables of interpolated function", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

f:

-

g: $f

- -

f(3) = $$f(3)

-

f(4) = $$f(4)

-

f(5) = $$f(5)

-

g(3) = $$g(3)

-

g(4) = $$g(4)

-

g(5) = $$g(5)

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.log("initial state"); - - cy.get(cesc("#\\/pf1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/pf2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/pf3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/pg1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/pg2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/pg3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - }); - - it("evaluate at asymptotes", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

f1: 1/x

-

f2: 1/(-x)

-

f3: -1/x

-

f4: -1/(-x)

-

f5: 1/(x(x-1))

-

f6: 1/(x(x+1))

-

f7: 1/(x(x+1)(x-1))

-

f5a: 1/x*1/(x-1)

-

f6a: 1/x*1/(x+1)

-

f7a: 1/x*1/(x+1)*1/(x-1)

- -

-

-

-

-

-

-

-

- -

-

-

-

- -

-

-

-

- -

-

-

-

-

-

- - -

-

-

-

- -

-

-

-

- -

-

-

-

-

-

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/f10n")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("∞"); - }); - cy.get(cesc("#\\/f10s")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("∞"); - }); - - cy.get(cesc("#\\/f20n")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−∞"); - }); - cy.get(cesc("#\\/f20s")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−∞"); - }); - - cy.get(cesc("#\\/f30n")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−∞"); - }); - cy.get(cesc("#\\/f30s")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−∞"); - }); - - cy.get(cesc("#\\/f40n")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("∞"); - }); - cy.get(cesc("#\\/f40s")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("∞"); - }); - - cy.get(cesc("#\\/f50n")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−∞"); - }); - cy.get(cesc("#\\/f50s")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−∞"); - }); - cy.get(cesc("#\\/f51n")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("∞"); - }); - cy.get(cesc("#\\/f51s")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("∞"); - }); - - cy.get(cesc("#\\/f60n")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("∞"); - }); - cy.get(cesc("#\\/f60s")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("∞"); - }); - cy.get(cesc("#\\/f6n1n")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−∞"); - }); - cy.get(cesc("#\\/f6n1s")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−∞"); - }); - - cy.get(cesc("#\\/f70n")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−∞"); - }); - cy.get(cesc("#\\/f70s")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−∞"); - }); - cy.get(cesc("#\\/f71n")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("∞"); - }); - cy.get(cesc("#\\/f71s")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("∞"); - }); - cy.get(cesc("#\\/f7n1n")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("∞"); - }); - cy.get(cesc("#\\/f7n1s")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("∞"); - }); - - cy.get(cesc("#\\/f5a0n")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−∞"); - }); - cy.get(cesc("#\\/f5a0s")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−∞"); - }); - cy.get(cesc("#\\/f5a1n")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("∞"); - }); - cy.get(cesc("#\\/f5a1s")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("∞"); - }); - - cy.get(cesc("#\\/f6a0n")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("∞"); - }); - cy.get(cesc("#\\/f6a0s")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("∞"); - }); - cy.get(cesc("#\\/f6an1n")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−∞"); - }); - cy.get(cesc("#\\/f6an1s")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−∞"); - }); - - cy.get(cesc("#\\/f7a0n")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−∞"); - }); - cy.get(cesc("#\\/f7a0s")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−∞"); - }); - cy.get(cesc("#\\/f7a1n")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("∞"); - }); - cy.get(cesc("#\\/f7a1s")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("∞"); - }); - cy.get(cesc("#\\/f7an1n")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("∞"); - }); - cy.get(cesc("#\\/f7an1s")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("∞"); - }); - }); - - it("evaluate at infinity", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

f1: 1/x

-

f2: 1/(-x)

-

f3: x^3

-

f4: (-x)^3

-

f5: sin(x)

- -

-

-

-

- -

-

-

-

- -

-

-

-

- -

-

-

-

- -

-

-

-

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/f1pn")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f1ps")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f1mn")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f1ms")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - - cy.get(cesc("#\\/f2pn")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f2ps")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f2mn")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f2ms")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - - cy.get(cesc("#\\/f3pn")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("∞"); - }); - cy.get(cesc("#\\/f3ps")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("∞"); - }); - cy.get(cesc("#\\/f3mn")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−∞"); - }); - cy.get(cesc("#\\/f3ms")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−∞"); - }); - - cy.get(cesc("#\\/f4pn")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−∞"); - }); - cy.get(cesc("#\\/f4ps")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−∞"); - }); - cy.get(cesc("#\\/f4mn")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("∞"); - }); - cy.get(cesc("#\\/f4ms")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("∞"); - }); - - cy.get(cesc("#\\/f5pn")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f5ps")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(∞)"); - }); - cy.get(cesc("#\\/f5mn")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f5ms")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(−∞)"); - }); - }); - - it("evaluate at infinity, interpolated functions", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

f1:

-

f2:

-

f3:

-

f4:

-

f5:

- -

-

- -

-

- -

-

- -

-

- -

-

- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/f1pn") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc2("#/f1mn") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - - cy.get(cesc2("#/f2pn") + " .mjx-mrow") - .eq(0) - .should("have.text", "∞"); - cy.get(cesc2("#/f2mn") + " .mjx-mrow") - .eq(0) - .should("have.text", "−∞"); - - cy.get(cesc2("#/f3pn") + " .mjx-mrow") - .eq(0) - .should("have.text", "−∞"); - cy.get(cesc2("#/f3mn") + " .mjx-mrow") - .eq(0) - .should("have.text", "∞"); - - cy.get(cesc2("#/f4pn") + " .mjx-mrow") - .eq(0) - .should("have.text", "−∞"); - cy.get(cesc2("#/f4mn") + " .mjx-mrow") - .eq(0) - .should("have.text", "∞"); - - cy.get(cesc2("#/f5pn") + " .mjx-mrow") - .eq(0) - .should("have.text", "∞"); - cy.get(cesc2("#/f5mn") + " .mjx-mrow") - .eq(0) - .should("have.text", "−∞"); - }); - - it("evaluate at domain boundary, numeric", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

f1: sin(x)

-

f2: sin(x)

-

f3: sin(x)

-

f4: sin(x)

- -

-

-

- -

-

-

- -

-

-

- -

-

-

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/f1l")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f1r")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f1m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - - cy.get(cesc("#\\/f2l")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f2r")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f2m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - - cy.get(cesc("#\\/f3l")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f3r")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f3m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - - cy.get(cesc("#\\/f4l")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f4r")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f4m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - - cy.log("test creating function from definition"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f1 = createFunctionFromDefinition( - stateVariables["/f1"].stateValues.fDefinitions[0], - ); - let f2 = createFunctionFromDefinition( - stateVariables["/f2"].stateValues.fDefinitions[0], - ); - let f3 = createFunctionFromDefinition( - stateVariables["/f3"].stateValues.fDefinitions[0], - ); - let f4 = createFunctionFromDefinition( - stateVariables["/f4"].stateValues.fDefinitions[0], - ); - - expect(f1(-Math.PI)).eqls(NaN); - expect(f1(0)).eqls(0); - expect(f1(Math.PI)).eqls(NaN); - expect(f2(-Math.PI)).eqls(NaN); - expect(f2(0)).eqls(0); - expect(f2(Math.PI)).closeTo(0, 1e-14); - expect(f3(-Math.PI)).closeTo(0, 1e-14); - expect(f3(0)).eqls(0); - expect(f3(Math.PI)).closeTo(0, 1e-14); - expect(f4(-Math.PI)).closeTo(0, 1e-14); - expect(f4(0)).eqls(0); - expect(f4(Math.PI)).eqls(NaN); - }); - }); - - it("evaluate at domain boundary, symbolic", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

f1: sin(x)

-

f2: sin(x)

-

f3: sin(x)

-

f4: sin(x)

- -

-

-

-

- -

-

-

-

- -

-

-

-

- -

-

-

-

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/f1l")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/f1r")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/f1m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f1y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(10y)"); - }); - - cy.get(cesc("#\\/f2l")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/f2r")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π)"); // eventually should be '0' once can simplify sin(pi) - }); - cy.get(cesc("#\\/f2m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f2y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(10y)"); - }); - - cy.get(cesc("#\\/f3l")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(−π)"); // eventually should be '0' once can simplify sin(-pi) - }); - cy.get(cesc("#\\/f3r")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π)"); // eventually should be '0' once can simplify sin(pi) - }); - cy.get(cesc("#\\/f3m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f3y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(10y)"); - }); - - cy.get(cesc("#\\/f4l")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(−π)"); // eventually should be '0' once can simplify sin(-pi) - }); - cy.get(cesc("#\\/f4r")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/f4m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f4y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(10y)"); - }); - }); - - it("evaluate at domain boundary, numeric, multidimensional", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

f1: sin(x+y)

-

f2: sin(x+y)

-

f3: sin(x+y)

-

f4: sin(x+y)

- -

-

-

-

-

-

-

-

-

- -

-

-

-

-

-

-

-

-

- -

-

-

-

-

-

-

-

-

- -

-

-

-

-

-

-

-

-

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/f1ll")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f1lr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f1lm")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f1rl")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f1rr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f1rm")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f1ml")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f1mr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f1mm")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - - cy.get(cesc("#\\/f2ll")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f2lr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f2lm")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f2rl")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f2rr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f2rm")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f2ml")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f2mr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f2mm")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - - cy.get(cesc("#\\/f3ll")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f3lr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f3lm")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f3rl")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f3rr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f3rm")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f3ml")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f3mr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f3mm")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - - cy.get(cesc("#\\/f4ll")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f4lr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f4lm")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f4rl")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f4rr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f4rm")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f4ml")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f4mr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f4mm")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - - cy.log("test creating function from definition"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f1 = createFunctionFromDefinition( - stateVariables["/f1"].stateValues.fDefinitions[0], - ); - let f2 = createFunctionFromDefinition( - stateVariables["/f2"].stateValues.fDefinitions[0], - ); - let f3 = createFunctionFromDefinition( - stateVariables["/f3"].stateValues.fDefinitions[0], - ); - let f4 = createFunctionFromDefinition( - stateVariables["/f4"].stateValues.fDefinitions[0], - ); - - expect(f1(-Math.PI, -Math.PI)).eqls(NaN); - expect(f1(-Math.PI, 0)).eqls(NaN); - expect(f1(-Math.PI, Math.PI)).eqls(NaN); - expect(f1(0, -Math.PI)).eqls(NaN); - expect(f1(0, 0)).eqls(0); - expect(f1(0, Math.PI)).eqls(NaN); - expect(f1(Math.PI, -Math.PI)).eqls(NaN); - expect(f1(Math.PI, 0)).eqls(NaN); - expect(f1(Math.PI, Math.PI)).eqls(NaN); - - expect(f2(-Math.PI, -Math.PI)).eqls(NaN); - expect(f2(-Math.PI, 0)).eqls(NaN); - expect(f2(-Math.PI, Math.PI)).eqls(NaN); - expect(f2(0, -Math.PI)).eqls(NaN); - expect(f2(0, 0)).eqls(0); - expect(f2(0, Math.PI)).closeTo(0, 1e-14); - expect(f2(Math.PI, -Math.PI)).eqls(NaN); - expect(f2(Math.PI, 0)).closeTo(0, 1e-14); - expect(f2(Math.PI, Math.PI)).closeTo(0, 1e-14); - - expect(f3(-Math.PI, -Math.PI)).closeTo(0, 1e-14); - expect(f3(-Math.PI, 0)).closeTo(0, 1e-14); - expect(f3(-Math.PI, Math.PI)).closeTo(0, 1e-14); - expect(f3(0, -Math.PI)).closeTo(0, 1e-14); - expect(f3(0, 0)).eqls(0); - expect(f3(0, Math.PI)).closeTo(0, 1e-14); - expect(f3(Math.PI, -Math.PI)).closeTo(0, 1e-14); - expect(f3(Math.PI, 0)).closeTo(0, 1e-14); - expect(f3(Math.PI, Math.PI)).closeTo(0, 1e-14); - - expect(f4(-Math.PI, -Math.PI)).closeTo(0, 1e-14); - expect(f4(-Math.PI, 0)).closeTo(0, 1e-14); - expect(f4(-Math.PI, Math.PI)).eqls(NaN); - expect(f4(0, -Math.PI)).closeTo(0, 1e-14); - expect(f4(0, 0)).eqls(0); - expect(f4(0, Math.PI)).eqls(NaN); - expect(f4(Math.PI, -Math.PI)).eqls(NaN); - expect(f4(Math.PI, 0)).eqls(NaN); - expect(f4(Math.PI, Math.PI)).eqls(NaN); - }); - }); - - it("evaluate at domain boundary, symbolic, multidimensional", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

f1: sin(x+y)

-

f2: sin(x+y)

-

f3: sin(x+y)

-

f4: sin(x+y)

- -

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

- -

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

- -

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

- -

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/f1ll")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/f1lr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/f1lm")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/f1ly")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(−π+10y)"); - }); - cy.get(cesc("#\\/f1rl")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/f1rr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/f1rm")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/f1ry")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π+10y)"); - }); - cy.get(cesc("#\\/f1ml")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/f1mr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/f1mm")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f1my")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(10y)"); - }); - cy.get(cesc("#\\/f1yl")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(−π+10y)"); - }); - cy.get(cesc("#\\/f1yr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π+10y)"); - }); - cy.get(cesc("#\\/f1ym")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(10y)"); - }); - cy.get(cesc("#\\/f1yy")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(20y)"); - }); - - cy.get(cesc("#\\/f2ll")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/f2lr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/f2lm")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/f2ly")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(−π+10y)"); - }); - cy.get(cesc("#\\/f2rl")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/f2rr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(2π)"); - }); - cy.get(cesc("#\\/f2rm")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π)"); - }); - cy.get(cesc("#\\/f2ry")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π+10y)"); - }); - cy.get(cesc("#\\/f2ml")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/f2mr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π)"); - }); - cy.get(cesc("#\\/f2mm")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f2my")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(10y)"); - }); - cy.get(cesc("#\\/f2yl")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(−π+10y)"); - }); - cy.get(cesc("#\\/f2yr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π+10y)"); - }); - cy.get(cesc("#\\/f2ym")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(10y)"); - }); - cy.get(cesc("#\\/f2yy")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(20y)"); - }); - - cy.get(cesc("#\\/f3ll")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(−2π)"); - }); - cy.get(cesc("#\\/f3lr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f3lm")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(−π)"); - }); - cy.get(cesc("#\\/f3ly")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(−π+10y)"); - }); - cy.get(cesc("#\\/f3rl")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f3rr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(2π)"); - }); - cy.get(cesc("#\\/f3rm")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π)"); - }); - cy.get(cesc("#\\/f3ry")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π+10y)"); - }); - cy.get(cesc("#\\/f3ml")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(−π)"); - }); - cy.get(cesc("#\\/f3mr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π)"); - }); - cy.get(cesc("#\\/f3mm")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f3my")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(10y)"); - }); - cy.get(cesc("#\\/f3yl")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(−π+10y)"); - }); - cy.get(cesc("#\\/f3yr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π+10y)"); - }); - cy.get(cesc("#\\/f3ym")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(10y)"); - }); - cy.get(cesc("#\\/f3yy")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(20y)"); - }); - - cy.get(cesc("#\\/f4ll")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(−2π)"); - }); - cy.get(cesc("#\\/f4lr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/f4lm")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(−π)"); - }); - cy.get(cesc("#\\/f4ly")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(−π+10y)"); - }); - cy.get(cesc("#\\/f4rl")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/f4rr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/f4rm")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/f4ry")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π+10y)"); - }); - cy.get(cesc("#\\/f4ml")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(−π)"); - }); - cy.get(cesc("#\\/f4mr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/f4mm")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f4my")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(10y)"); - }); - cy.get(cesc("#\\/f4yl")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(−π+10y)"); - }); - cy.get(cesc("#\\/f4yr")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(π+10y)"); - }); - cy.get(cesc("#\\/f4ym")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(10y)"); - }); - cy.get(cesc("#\\/f4yy")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(20y)"); - }); - }); - - it("evaluate interpolated at domain boundary", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

f1:

-

f2:

-

f3:

-

f4:

- -

-

-

- -

-

-

- -

-

-

- -

-

-

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/f1l")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f1r")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f1m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - - cy.get(cesc("#\\/f2l")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f2r")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−1"); - }); - cy.get(cesc("#\\/f2m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - - cy.get(cesc("#\\/f3l")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/f3r")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−1"); - }); - cy.get(cesc("#\\/f3m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - - cy.get(cesc("#\\/f4l")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/f4r")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f4m")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - }); - - it("evaluate functions based on functions, symbolic", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

f: x^2

-

fa: $$f(x)

-

fxp1: $$f(x+1)

-

fp1: $$f(x)+1

-

fp1a: $$f(x)+1

-

fxp1p1: $$f(x+1)+1

-

fm: $$f(x)

-

fp1m: $$f(x)+1

- -

-

-

-

- -

-

-

-

- -

-

-

-

- -

-

-

-

- -

-

-

-

- -

-

-

-

- -

-

-

-

- -

-

-

-

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/f0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/f1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/f2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/f3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - - cy.get(cesc("#\\/fa0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/fa1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/fa2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/fa3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - - cy.get(cesc("#\\/fxp10")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/fxp11")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/fxp12")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/fxp13")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - - cy.get(cesc("#\\/fp10")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f+1"); - }); - cy.get(cesc("#\\/fp11")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/fp12")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc("#\\/fp13")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f+1"); - }); - - cy.get(cesc("#\\/fp1a0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f+1"); - }); - cy.get(cesc("#\\/fp1a1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/fp1a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc("#\\/fp1a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f+1"); - }); - - cy.get(cesc("#\\/fxp1p10")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/fxp1p11")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc("#\\/fxp1p12")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f+1"); - }); - cy.get(cesc("#\\/fxp1p13")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f+1"); - }); - - cy.get(cesc("#\\/fm0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/fm1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/fm2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/fm3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9"); - }); - - cy.get(cesc("#\\/fp1m0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/fp1m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/fp1m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc("#\\/fp1m3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("10"); - }); - }); - - it("evaluate functions based on functions, numeric", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

f: x^2

-

fa: $$f(x)

-

fxp1: $$f(x+1)

-

fp1: $$f(x)+1

-

fp1a: $$f(x)+1

-

fxp1p1: $$f(x+1)+1

-

fm: $$f(x)

-

fp1m: $$f(x)+1

- -

-

-

-

- -

-

-

-

- -

-

-

-

- -

-

-

-

- -

-

-

-

- -

-

-

-

- -

-

-

-

- -

-

-

-

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/f0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/f2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/f3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - - cy.get(cesc("#\\/fa0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/fa1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/fa2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/fa3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - - cy.get(cesc("#\\/fxp10")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/fxp11")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/fxp12")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/fxp13")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - - cy.get(cesc("#\\/fp10")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/fp11")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/fp12")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc("#\\/fp13")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - - cy.get(cesc("#\\/fp1a0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/fp1a1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/fp1a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc("#\\/fp1a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - - cy.get(cesc("#\\/fxp1p10")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/fxp1p11")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc("#\\/fxp1p12")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/fxp1p13")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - - cy.get(cesc("#\\/fm0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/fm1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/fm2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/fm3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - - cy.get(cesc("#\\/fp1m0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/fp1m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/fp1m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/fp1m3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - - cy.log("test creating function from definition"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/f"].stateValues.fDefinitions[0], - ); - let fa = createFunctionFromDefinition( - stateVariables["/fa"].stateValues.fDefinitions[0], - ); - let fxp1 = createFunctionFromDefinition( - stateVariables["/fxp1"].stateValues.fDefinitions[0], - ); - let fp1 = createFunctionFromDefinition( - stateVariables["/fp1"].stateValues.fDefinitions[0], - ); - let fp1a = createFunctionFromDefinition( - stateVariables["/fp1a"].stateValues.fDefinitions[0], - ); - let fxp1p1 = createFunctionFromDefinition( - stateVariables["/fxp1p1"].stateValues.fDefinitions[0], - ); - let fm = createFunctionFromDefinition( - stateVariables["/fm"].stateValues.fDefinitions[0], - ); - let fp1m = createFunctionFromDefinition( - stateVariables["/fp1m"].stateValues.fDefinitions[0], - ); - - expect(f(0)).eqls(NaN); - expect(f(1)).eqls(1); - expect(f(2)).eqls(4); - expect(f(3)).eqls(NaN); - - expect(fa(0)).eqls(NaN); - expect(fa(1)).eqls(1); - expect(fa(2)).eqls(4); - expect(fa(3)).eqls(NaN); - - expect(fxp1(0)).eqls(1); - expect(fxp1(1)).eqls(4); - expect(fxp1(2)).eqls(NaN); - expect(fxp1(3)).eqls(NaN); - - expect(fp1(0)).eqls(NaN); - expect(fp1(1)).eqls(2); - expect(fp1(2)).eqls(5); - expect(fp1(3)).eqls(NaN); - - expect(fp1a(0)).eqls(NaN); - expect(fp1a(1)).eqls(2); - expect(fp1a(2)).eqls(5); - expect(fp1a(3)).eqls(NaN); - - expect(fxp1p1(0)).eqls(2); - expect(fxp1p1(1)).eqls(5); - expect(fxp1p1(2)).eqls(NaN); - expect(fxp1p1(3)).eqls(NaN); - - expect(fm(0)).eqls(NaN); - expect(fm(1)).eqls(NaN); - expect(fm(2)).eqls(NaN); - expect(fm(3)).eqls(NaN); - - expect(fp1m(0)).eqls(NaN); - expect(fp1m(1)).eqls(NaN); - expect(fp1m(2)).eqls(NaN); - expect(fp1m(3)).eqls(NaN); - }); - }); - - it("evaluate functions based on functions, numeric then symbolic", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

f: x^2

-

fa: $$f(x)

-

fxp1: $$f(x+1)

-

fpy: $$f(x)+y

-

fpya: $$f(x)+y

-

fxp1py: $$f(x+1)+y

-

fm: $$f(x)

-

fpym: $$f(x)+y

- -

-

-

-

- -

-

-

-

- -

-

-

-

- -

-

-

-

- -

-

-

-

- -

-

-

-

- -

-

-

-

- -

-

-

-

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/f0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/f1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/f2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/f3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - - cy.get(cesc("#\\/fa0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/fa1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/fa2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/fa3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - - cy.get(cesc("#\\/fxp10")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/fxp11")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/fxp12")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/fxp13")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - - cy.get(cesc("#\\/fpy0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y+NaN"); - }); - cy.get(cesc("#\\/fpy1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y+1"); - }); - cy.get(cesc("#\\/fpy2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y+4"); - }); - cy.get(cesc("#\\/fpy3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y+NaN"); - }); - - cy.get(cesc("#\\/fpya0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y+NaN"); - }); - cy.get(cesc("#\\/fpya1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y+1"); - }); - cy.get(cesc("#\\/fpya2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y+4"); - }); - cy.get(cesc("#\\/fpya3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y+NaN"); - }); - - cy.get(cesc("#\\/fxp1py0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y+1"); - }); - cy.get(cesc("#\\/fxp1py1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y+4"); - }); - cy.get(cesc("#\\/fxp1py2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y+NaN"); - }); - cy.get(cesc("#\\/fxp1py3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y+NaN"); - }); - - cy.get(cesc("#\\/fm0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/fm1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/fm2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/fm3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - - cy.get(cesc("#\\/fpym0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y+NaN"); - }); - cy.get(cesc("#\\/fpym1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y+NaN"); - }); - cy.get(cesc("#\\/fpym2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y+NaN"); - }); - cy.get(cesc("#\\/fpym3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y+NaN"); - }); - }); - - it("evaluate functions based on functions, symbolic then numeric", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

f: x^2

-

fa: $$f(x)

-

fxp1: $$f(x+1)

-

fp1: $$f(x)+1

-

fp1a: $$f(x)+1

-

fxp1p1: $$f(x+1)+1

-

fm: $$f(x)

-

fp1m: $$f(x)+1

- -

-

-

-

- -

-

-

-

- -

-

-

-

- -

-

-

-

- -

-

-

-

- -

-

-

-

- -

-

-

-

- -

-

-

-

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/f0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/f1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/f2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/f3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - - cy.get(cesc("#\\/fa0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/fa1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/fa2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/fa3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - - cy.get(cesc("#\\/fxp10")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/fxp11")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/fxp12")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/fxp13")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - - cy.get(cesc("#\\/fp10")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/fp11")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/fp12")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc("#\\/fp13")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - - cy.get(cesc("#\\/fp1a0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/fp1a1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/fp1a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc("#\\/fp1a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - - cy.get(cesc("#\\/fxp1p10")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/fxp1p11")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc("#\\/fxp1p12")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/fxp1p13")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - - cy.get(cesc("#\\/fm0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/fm1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/fm2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/fm3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9"); - }); - - cy.get(cesc("#\\/fp1m0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/fp1m1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/fp1m2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc("#\\/fp1m3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("10"); - }); - - cy.log("test creating function from definition"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/f"].stateValues.fDefinitions[0], - ); - let fa = createFunctionFromDefinition( - stateVariables["/fa"].stateValues.fDefinitions[0], - ); - let fxp1 = createFunctionFromDefinition( - stateVariables["/fxp1"].stateValues.fDefinitions[0], - ); - let fp1 = createFunctionFromDefinition( - stateVariables["/fp1"].stateValues.fDefinitions[0], - ); - let fp1a = createFunctionFromDefinition( - stateVariables["/fp1a"].stateValues.fDefinitions[0], - ); - let fxp1p1 = createFunctionFromDefinition( - stateVariables["/fxp1p1"].stateValues.fDefinitions[0], - ); - let fm = createFunctionFromDefinition( - stateVariables["/fm"].stateValues.fDefinitions[0], - ); - let fp1m = createFunctionFromDefinition( - stateVariables["/fp1m"].stateValues.fDefinitions[0], - ); - - // Note: function from definition is numeric even for f itself, so returns NaNs - expect(f(0)).eqls(NaN); - expect(f(1)).eqls(1); - expect(f(2)).eqls(4); - expect(f(3)).eqls(NaN); - - expect(fa(0)).eqls(NaN); - expect(fa(1)).eqls(1); - expect(fa(2)).eqls(4); - expect(fa(3)).eqls(NaN); - - expect(fxp1(0)).eqls(1); - expect(fxp1(1)).eqls(4); - expect(fxp1(2)).eqls(NaN); - expect(fxp1(3)).eqls(NaN); - - expect(fp1(0)).eqls(NaN); - expect(fp1(1)).eqls(2); - expect(fp1(2)).eqls(5); - expect(fp1(3)).eqls(NaN); - - expect(fp1a(0)).eqls(NaN); - expect(fp1a(1)).eqls(2); - expect(fp1a(2)).eqls(5); - expect(fp1a(3)).eqls(NaN); - - expect(fxp1p1(0)).eqls(2); - expect(fxp1p1(1)).eqls(5); - expect(fxp1p1(2)).eqls(NaN); - expect(fxp1p1(3)).eqls(NaN); - - expect(fm(0)).eqls(0); - expect(fm(1)).eqls(1); - expect(fm(2)).eqls(4); - expect(fm(3)).eqls(9); - - expect(fp1m(0)).eqls(1); - expect(fp1m(1)).eqls(2); - expect(fp1m(2)).eqls(5); - expect(fp1m(3)).eqls(10); - }); - }); - - it("an evaluate copied into a function can be reevaluated", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 2x - - $$f(x) - $fx - $$f(x)+1 - $fx+1 -

$$g(2)

-

$$ga(2)

-

$$h(2)

-

$$ha(2)

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/f")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2x"); - }); - cy.get(cesc("#\\/fx")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("NaN"); - }); - cy.get(cesc("#\\/g")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/ga")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/h")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/ha")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/pg")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/pga")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/ph")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc("#\\/pha")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - }); - - it("evaluate functions based on interpolated function", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

f: x^2

-

fa: $$f(x)

-

fxp1: $$f(x+1)

-

fp1: $$f(x)+1

-

fp1a: $$f(x)+1

-

fxp1p1: $$f(x+1)+1

- -

-

-

-

- -

-

-

-

- -

-

-

-

- -

-

-

-

- -

-

-

-

- -

-

-

-

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/f0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/f1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/f2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/f3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - - cy.get(cesc("#\\/fa0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - cy.get(cesc("#\\/fa1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/fa2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/fa3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - - cy.get(cesc("#\\/fxp10")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/fxp11")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/fxp12")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/fxp13")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("0"); - }); - - cy.get(cesc("#\\/fp10")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/fp11")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/fp12")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc("#\\/fp13")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - - cy.get(cesc("#\\/fp1a0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/fp1a1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/fp1a2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc("#\\/fp1a3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - - cy.get(cesc("#\\/fxp1p10")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/fxp1p11")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(cesc("#\\/fxp1p12")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/fxp1p13")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - cy.log("test creating function from definition"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/f"].stateValues.fDefinitions[0], - ); - let fa = createFunctionFromDefinition( - stateVariables["/fa"].stateValues.fDefinitions[0], - ); - let fxp1 = createFunctionFromDefinition( - stateVariables["/fxp1"].stateValues.fDefinitions[0], - ); - let fp1 = createFunctionFromDefinition( - stateVariables["/fp1"].stateValues.fDefinitions[0], - ); - let fp1a = createFunctionFromDefinition( - stateVariables["/fp1a"].stateValues.fDefinitions[0], - ); - let fxp1p1 = createFunctionFromDefinition( - stateVariables["/fxp1p1"].stateValues.fDefinitions[0], - ); - - expect(f(3)).eqls(0); - expect(f(4)).eqls(3); - expect(f(5)).eqls(4); - expect(f(6)).eqls(3); - - expect(fa(3)).eqls(0); - expect(fa(4)).eqls(3); - expect(fa(5)).eqls(4); - expect(fa(6)).eqls(3); - - expect(fxp1(3)).eqls(3); - expect(fxp1(4)).eqls(4); - expect(fxp1(5)).eqls(3); - expect(fxp1(6)).eqls(0); - - expect(fp1(3)).eqls(1); - expect(fp1(4)).eqls(4); - expect(fp1(5)).eqls(5); - expect(fp1(6)).eqls(4); - - expect(fp1a(3)).eqls(1); - expect(fp1a(4)).eqls(4); - expect(fp1a(5)).eqls(5); - expect(fp1a(6)).eqls(4); - - expect(fxp1p1(3)).eqls(4); - expect(fxp1p1(4)).eqls(5); - expect(fxp1p1(5)).eqls(4); - expect(fxp1p1(6)).eqls(1); - }); - }); -}); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/extract.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/extract.cy.js deleted file mode 100644 index 4c52842e7..000000000 --- a/packages/test-cypress/cypress/e2e/tagSpecific/extract.cy.js +++ /dev/null @@ -1,2430 +0,0 @@ -import { cesc, cesc2 } from "@doenet/utils"; - -function nInDOM(n) { - if (n < 0) { - return `−${Math.abs(n)}`; - } else { - return String(n); - } -} - -describe("Extract Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("extract copies properties", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x - x - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log(`check properties`); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.modifyIndirectly).eq( - false, - ); - expect(stateVariables["/_math2"].stateValues.modifyIndirectly).eq( - true, - ); - expect(stateVariables["/e1"].stateValues.modifyIndirectly).eq( - false, - ); - expect(stateVariables["/e2"].stateValues.modifyIndirectly).eq(true); - }); - }); - - it("extract can overwrite basecomponent properties", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x - x - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log(`check properties`); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].stateValues.modifyIndirectly).eq( - false, - ); - expect(stateVariables["/_math2"].stateValues.modifyIndirectly).eq( - true, - ); - expect(stateVariables["/e1"].stateValues.modifyIndirectly).eq(true); - expect(stateVariables["/e2"].stateValues.modifyIndirectly).eq( - false, - ); - }); - }); - - it("extract multiple tags", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (1,2) - (3,4) - (5,6) - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/e1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/e2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc("#\\/e3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6"); - }); - - cy.log(`check properties`); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/e1"].stateValues.value).eq(2); - expect(stateVariables["/e2"].stateValues.value).eq(4); - expect(stateVariables["/e3"].stateValues.value).eq(6); - }); - }); - - it("extract still updatable", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - $original{name="copy"} - - ($copy2.y, - $copy{name="copy2"}) - - - - - (1,2) - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log(`initial position`); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/original"].stateValues.xs[0]).eq(1); - expect(stateVariables["/original"].stateValues.xs[1]).eq(2); - expect(stateVariables["/copy"].stateValues.xs[0]).eq(1); - expect(stateVariables["/copy"].stateValues.xs[1]).eq(2); - expect(stateVariables["/transformed"].stateValues.xs[0]).eq(2); - expect(stateVariables["/transformed"].stateValues.xs[1]).eq(1); - }); - - cy.log(`move original point`); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/original", - args: { x: -3, y: 5 }, - }); - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/original"].stateValues.xs[0]).eq(-3); - expect(stateVariables["/original"].stateValues.xs[1]).eq(5); - expect(stateVariables["/copy"].stateValues.xs[0]).eq(-3); - expect(stateVariables["/copy"].stateValues.xs[1]).eq(5); - expect(stateVariables["/transformed"].stateValues.xs[0]).eq(5); - expect(stateVariables["/transformed"].stateValues.xs[1]).eq(-3); - }); - - cy.log(`move copy point`); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/copy", - args: { x: 6, y: -9 }, - }); - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/original"].stateValues.xs[0]).eq(6); - expect(stateVariables["/original"].stateValues.xs[1]).eq(-9); - expect(stateVariables["/copy"].stateValues.xs[0]).eq(6); - expect(stateVariables["/copy"].stateValues.xs[1]).eq(-9); - expect(stateVariables["/transformed"].stateValues.xs[0]).eq(-9); - expect(stateVariables["/transformed"].stateValues.xs[1]).eq(6); - }); - - cy.log(`move transformed point`); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/transformed", - args: { x: -1, y: -7 }, - }); - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/original"].stateValues.xs[0]).eq(-7); - expect(stateVariables["/original"].stateValues.xs[1]).eq(-1); - expect(stateVariables["/copy"].stateValues.xs[0]).eq(-7); - expect(stateVariables["/copy"].stateValues.xs[1]).eq(-1); - expect(stateVariables["/transformed"].stateValues.xs[0]).eq(-1); - expect(stateVariables["/transformed"].stateValues.xs[1]).eq(-7); - }); - }); - - it("copy prop of extract", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - $_extract1.x{assignNames="x1"}, - $_extract1.y{assignNames="y1"} - - - (1,2) - (5,6) - $_extract1{assignNames="copiedextract"} - - - $copiedextract.x{assignNames="x2"}, - $copiedextract.y{assignNames="y2"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/x1"].stateValues.value).eq(3); - expect(stateVariables["/y1"].stateValues.value).eq(4); - expect(stateVariables["/x2"].stateValues.value).eq(3); - expect(stateVariables["/y2"].stateValues.value).eq(4); - }); - - cy.log("move extracted center"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/copiedextract", - args: { x: -2, y: -5 }, - }); - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/x1"].stateValues.value).closeTo(-2, 1e-12); - expect(stateVariables["/y1"].stateValues.value).closeTo(-5, 1e-12); - expect(stateVariables["/x2"].stateValues.value).closeTo(-2, 1e-12); - expect(stateVariables["/y2"].stateValues.value).closeTo(-5, 1e-12); - expect(stateVariables["/_point1"].stateValues.xs[0]).closeTo( - -4, - 1e-12, - ); - expect(stateVariables["/_point1"].stateValues.xs[1]).closeTo( - -7, - 1e-12, - ); - expect(stateVariables["/_point2"].stateValues.xs[0]).closeTo( - 0, - 1e-12, - ); - expect(stateVariables["/_point2"].stateValues.xs[1]).closeTo( - -3, - 1e-12, - ); - }); - - cy.log("move points 1 and 2"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 8, y: -1 }, - }); - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point2", - args: { x: -6, y: -7 }, - }); - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/x1"].stateValues.value).closeTo(1, 1e-12); - expect(stateVariables["/y1"].stateValues.value).closeTo(-4, 1e-12); - expect(stateVariables["/x2"].stateValues.value).closeTo(1, 1e-12); - expect(stateVariables["/y2"].stateValues.value).closeTo(-4, 1e-12); - }); - }); - - it("extract from sequence", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

- - - -

- -

$_extract1

- -

$_aslist2

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/_p1")).should("have.text", ""); - cy.get(cesc("#\\/_p2")).should("have.text", ""); - cy.get(cesc("#\\/_p3")).should("have.text", ""); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_aslist1"].activeChildren.map( - (x) => x.componentType, - ), - ).eqls([]); - expect( - stateVariables["/_aslist2"].activeChildren.map( - (x) => x.componentType, - ), - ).eqls([]); - expect( - stateVariables[ - stateVariables["/_p3"].activeChildren[0].componentName - ].activeChildren.map((x) => x.componentType), - ).eqls([]); - expect( - stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ), - ).eqls([]); - expect( - stateVariables["/_aslist2"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ), - ).eqls([]); - expect( - stateVariables[ - stateVariables["/_p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ), - ).eqls([]); - }); - - cy.log("set to 3"); - cy.get(cesc("#\\/n") + " textarea").type(`3{enter}`, { force: true }); - cy.get(cesc("#\\/_p1")).should("have.text", "1, 2, 3"); - cy.get(cesc("#\\/_p2")).should("have.text", "1, 2, 3"); - cy.get(cesc("#\\/_p3")).should("have.text", "1, 2, 3"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_aslist1"].activeChildren.map( - (x) => x.componentType, - ), - ).eqls(["text", "text", "text"]); - expect( - stateVariables["/_aslist2"].activeChildren.map( - (x) => x.componentType, - ), - ).eqls(["text", "text", "text"]); - expect( - stateVariables[ - stateVariables["/_p3"].activeChildren[0].componentName - ].activeChildren.map((x) => x.componentType), - ).eqls(["text", "text", "text"]); - expect( - stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ), - ).eqls(["1", "2", "3"]); - expect( - stateVariables["/_aslist2"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ), - ).eqls(["1", "2", "3"]); - expect( - stateVariables[ - stateVariables["/_p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ), - ).eqls(["1", "2", "3"]); - }); - - cy.log("increase to 4"); - cy.get(cesc("#\\/n") + " textarea").type(`{end}{backspace}4{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_p1")).should("have.text", "1, 2, 3, 4"); - cy.get(cesc("#\\/_p2")).should("have.text", "1, 2, 3, 4"); - cy.get(cesc("#\\/_p3")).should("have.text", "1, 2, 3, 4"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_aslist1"].activeChildren.map( - (x) => x.componentType, - ), - ).eqls(["text", "text", "text", "text"]); - expect( - stateVariables["/_aslist2"].activeChildren.map( - (x) => x.componentType, - ), - ).eqls(["text", "text", "text", "text"]); - expect( - stateVariables[ - stateVariables["/_p3"].activeChildren[0].componentName - ].activeChildren.map((x) => x.componentType), - ).eqls(["text", "text", "text", "text"]); - expect( - stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ), - ).eqls(["1", "2", "3", "4"]); - expect( - stateVariables["/_aslist2"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ), - ).eqls(["1", "2", "3", "4"]); - expect( - stateVariables[ - stateVariables["/_p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ), - ).eqls(["1", "2", "3", "4"]); - }); - - cy.log("decrease to 2"); - cy.get(cesc("#\\/n") + " textarea").type(`{end}{backspace}2{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_p1")).should("have.text", "1, 2"); - cy.get(cesc("#\\/_p2")).should("have.text", "1, 2"); - cy.get(cesc("#\\/_p3")).should("have.text", "1, 2"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_aslist1"].activeChildren.map( - (x) => x.componentType, - ), - ).eqls(["text", "text"]); - expect( - stateVariables["/_aslist2"].activeChildren.map( - (x) => x.componentType, - ), - ).eqls(["text", "text"]); - expect( - stateVariables[ - stateVariables["/_p3"].activeChildren[0].componentName - ].activeChildren.map((x) => x.componentType), - ).eqls(["text", "text"]); - expect( - stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ), - ).eqls(["1", "2"]); - expect( - stateVariables["/_aslist2"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ), - ).eqls(["1", "2"]); - expect( - stateVariables[ - stateVariables["/_p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ), - ).eqls(["1", "2"]); - }); - - cy.log("increase to 5"); - cy.get(cesc("#\\/n") + " textarea").type(`{end}{backspace}5{enter}`, { - force: true, - }); - cy.get(cesc("#\\/_p1")).should("have.text", "1, 2, 3, 4, 5"); - cy.get(cesc("#\\/_p2")).should("have.text", "1, 2, 3, 4, 5"); - cy.get(cesc("#\\/_p3")).should("have.text", "1, 2, 3, 4, 5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_aslist1"].activeChildren.map( - (x) => x.componentType, - ), - ).eqls(["text", "text", "text", "text", "text"]); - expect( - stateVariables["/_aslist2"].activeChildren.map( - (x) => x.componentType, - ), - ).eqls(["text", "text", "text", "text", "text"]); - expect( - stateVariables[ - stateVariables["/_p3"].activeChildren[0].componentName - ].activeChildren.map((x) => x.componentType), - ).eqls(["text", "text", "text", "text", "text"]); - expect( - stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ), - ).eqls(["1", "2", "3", "4", "5"]); - expect( - stateVariables["/_aslist2"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ), - ).eqls(["1", "2", "3", "4", "5"]); - expect( - stateVariables[ - stateVariables["/_p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ), - ).eqls(["1", "2", "3", "4", "5"]); - }); - }); - - it("extract from map", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - -

- - - - - - - - -

- -

$_extract1

- -

$_aslist2

- -

$n.value{assignNames="n2"} - $m.value{assignNames="m2"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/_p1")).should("have.text", ""); - cy.get(cesc("#\\/_p2")).should("have.text", ""); - cy.get(cesc("#\\/_p3")).should("have.text", ""); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_aslist1"].activeChildren.map( - (x) => x.componentType, - ), - ).eqls([]); - expect( - stateVariables["/_aslist2"].activeChildren.map( - (x) => x.componentType, - ), - ).eqls([]); - expect( - stateVariables[ - stateVariables["/_p3"].activeChildren[0].componentName - ].activeChildren.map((x) => x.componentType), - ).eqls([]); - expect( - stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ), - ).eqls([]); - expect( - stateVariables["/_aslist2"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ), - ).eqls([]); - expect( - stateVariables[ - stateVariables["/_p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ), - ).eqls([]); - }); - - cy.log("set n to 3"); - cy.get(cesc("#\\/n") + " textarea").type(`3{enter}`, { force: true }); - cy.get(cesc("#\\/n2")).should("contain.text", "3"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let aslist1 = stateVariables["/_p1"].activeChildren[0]; - let aslist2 = stateVariables["/_p2"].activeChildren[0]; - let aslist3 = stateVariables["/_p3"].activeChildren[0]; - for (let i = 0; i < 3; i++) { - cy.get( - cesc2( - `#${ - stateVariables[aslist1.componentName] - .activeChildren[i].componentName - }`, - ), - ) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${i + 1}+_`); - }); - cy.get( - cesc2( - `#${ - stateVariables[aslist2.componentName] - .activeChildren[i].componentName - }`, - ), - ) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${i + 1}+_`); - }); - cy.get( - cesc2( - `#${ - stateVariables[aslist3.componentName] - .activeChildren[i].componentName - }`, - ), - ) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${i + 1}+_`); - }); - } - - // Note: put in another .then so test execute in order they appear here - // (so easier to find test results) - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_aslist1"].activeChildren.map( - (x) => x.componentType, - ), - ).eqls(["math", "math", "math"]); - expect( - stateVariables["/_aslist2"].activeChildren.map( - (x) => x.componentType, - ), - ).eqls(["math", "math", "math"]); - expect( - stateVariables[ - stateVariables["/_p3"].activeChildren[0].componentName - ].activeChildren.map((x) => x.componentType), - ).eqls(["math", "math", "math"]); - expect( - stateVariables["/_aslist1"].activeChildren.map( - (x) => - stateVariables[x.componentName].stateValues.value, - ), - ).eqls([ - ["+", 1, "_"], - ["+", 2, "_"], - ["+", 3, "_"], - ]); - expect( - stateVariables["/_aslist2"].activeChildren.map( - (x) => - stateVariables[x.componentName].stateValues.value, - ), - ).eqls([ - ["+", 1, "_"], - ["+", 2, "_"], - ["+", 3, "_"], - ]); - expect( - stateVariables[ - stateVariables["/_p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => - stateVariables[x.componentName].stateValues.value, - ), - ).eqls([ - ["+", 1, "_"], - ["+", 2, "_"], - ["+", 3, "_"], - ]); - }); - }); - - cy.log("set m to 7"); - cy.get(cesc("#\\/m") + " textarea").type(`7{enter}`, { force: true }); - cy.get(cesc("#\\/m2")).should("contain.text", "7"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let aslist1 = stateVariables["/_p1"].activeChildren[0]; - let aslist2 = stateVariables["/_p2"].activeChildren[0]; - let aslist3 = stateVariables["/_p3"].activeChildren[0]; - for (let i = 0; i < 3; i++) { - cy.get( - cesc2( - `#${ - stateVariables[aslist1.componentName] - .activeChildren[i].componentName - }`, - ), - ) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${i + 8}`); - }); - cy.get( - cesc2( - `#${ - stateVariables[aslist2.componentName] - .activeChildren[i].componentName - }`, - ), - ) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${i + 8}`); - }); - cy.get( - cesc2( - `#${ - stateVariables[aslist3.componentName] - .activeChildren[i].componentName - }`, - ), - ) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${i + 8}`); - }); - } - - // Note: put in another .then so test execute in order they appear here - // (so easier to find test results) - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_aslist1"].activeChildren.map( - (x) => x.componentType, - ), - ).eqls(["math", "math", "math"]); - expect( - stateVariables["/_aslist2"].activeChildren.map( - (x) => x.componentType, - ), - ).eqls(["math", "math", "math"]); - expect( - stateVariables[ - stateVariables["/_p3"].activeChildren[0].componentName - ].activeChildren.map((x) => x.componentType), - ).eqls(["math", "math", "math"]); - expect( - stateVariables["/_aslist1"].activeChildren.map( - (x) => - stateVariables[x.componentName].stateValues.value, - ), - ).eqls([8, 9, 10]); - expect( - stateVariables["/_aslist2"].activeChildren.map( - (x) => - stateVariables[x.componentName].stateValues.value, - ), - ).eqls([8, 9, 10]); - expect( - stateVariables[ - stateVariables["/_p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => - stateVariables[x.componentName].stateValues.value, - ), - ).eqls([8, 9, 10]); - }); - }); - - cy.log("increase n to 4"); - cy.get(cesc("#\\/n") + " textarea").type(`{end}{backspace}4{enter}`, { - force: true, - }); - cy.get(cesc("#\\/n2")).should("contain.text", "4"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let aslist1 = stateVariables["/_p1"].activeChildren[0]; - let aslist2 = stateVariables["/_p2"].activeChildren[0]; - let aslist3 = stateVariables["/_p3"].activeChildren[0]; - for (let i = 0; i < 4; i++) { - cy.get( - cesc2( - `#${ - stateVariables[aslist1.componentName] - .activeChildren[i].componentName - }`, - ), - ) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${i + 8}`); - }); - cy.get( - cesc2( - `#${ - stateVariables[aslist2.componentName] - .activeChildren[i].componentName - }`, - ), - ) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${i + 8}`); - }); - cy.get( - cesc2( - `#${ - stateVariables[aslist3.componentName] - .activeChildren[i].componentName - }`, - ), - ) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${i + 8}`); - }); - } - - // Note: put in another .then so test execute in order they appear here - // (so easier to find test results) - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_aslist1"].activeChildren.map( - (x) => x.componentType, - ), - ).eqls(["math", "math", "math", "math"]); - expect( - stateVariables["/_aslist2"].activeChildren.map( - (x) => x.componentType, - ), - ).eqls(["math", "math", "math", "math"]); - expect( - stateVariables[ - stateVariables["/_p3"].activeChildren[0].componentName - ].activeChildren.map((x) => x.componentType), - ).eqls(["math", "math", "math", "math"]); - expect( - stateVariables["/_aslist1"].activeChildren.map( - (x) => - stateVariables[x.componentName].stateValues.value, - ), - ).eqls([8, 9, 10, 11]); - expect( - stateVariables["/_aslist2"].activeChildren.map( - (x) => - stateVariables[x.componentName].stateValues.value, - ), - ).eqls([8, 9, 10, 11]); - expect( - stateVariables[ - stateVariables["/_p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => - stateVariables[x.componentName].stateValues.value, - ), - ).eqls([8, 9, 10, 11]); - }); - }); - - cy.log("change m to q"); - cy.get(cesc("#\\/m") + " textarea").type(`{end}{backspace}q{enter}`, { - force: true, - }); - cy.get(cesc("#\\/m2")).should("contain.text", "q"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let aslist1 = stateVariables["/_p1"].activeChildren[0]; - let aslist2 = stateVariables["/_p2"].activeChildren[0]; - let aslist3 = stateVariables["/_p3"].activeChildren[0]; - for (let i = 0; i < 4; i++) { - cy.get( - cesc2( - `#${ - stateVariables[aslist1.componentName] - .activeChildren[i].componentName - }`, - ), - ) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`q+${i + 1}`); - }); - cy.get( - cesc2( - `#${ - stateVariables[aslist2.componentName] - .activeChildren[i].componentName - }`, - ), - ) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`q+${i + 1}`); - }); - cy.get( - cesc2( - `#${ - stateVariables[aslist3.componentName] - .activeChildren[i].componentName - }`, - ), - ) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`q+${i + 1}`); - }); - } - - // Note: put in another .then so test execute in order they appear here - // (so easier to find test results) - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_aslist1"].activeChildren.map( - (x) => x.componentType, - ), - ).eqls(["math", "math", "math", "math"]); - expect( - stateVariables["/_aslist2"].activeChildren.map( - (x) => x.componentType, - ), - ).eqls(["math", "math", "math", "math"]); - expect( - stateVariables[ - stateVariables["/_p3"].activeChildren[0].componentName - ].activeChildren.map((x) => x.componentType), - ).eqls(["math", "math", "math", "math"]); - expect( - stateVariables["/_aslist1"].activeChildren.map( - (x) => - stateVariables[x.componentName].stateValues.value, - ), - ).eqls([ - ["+", "q", 1], - ["+", "q", 2], - ["+", "q", 3], - ["+", "q", 4], - ]); - expect( - stateVariables["/_aslist2"].activeChildren.map( - (x) => - stateVariables[x.componentName].stateValues.value, - ), - ).eqls([ - ["+", "q", 1], - ["+", "q", 2], - ["+", "q", 3], - ["+", "q", 4], - ]); - expect( - stateVariables[ - stateVariables["/_p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => - stateVariables[x.componentName].stateValues.value, - ), - ).eqls([ - ["+", "q", 1], - ["+", "q", 2], - ["+", "q", 3], - ["+", "q", 4], - ]); - }); - }); - - cy.log("decrease n to 2"); - cy.get(cesc("#\\/n") + " textarea").type(`{end}{backspace}2{enter}`, { - force: true, - }); - cy.get(cesc("#\\/n2")).should("contain.text", "2"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let aslist1 = stateVariables["/_p1"].activeChildren[0]; - let aslist2 = stateVariables["/_p2"].activeChildren[0]; - let aslist3 = stateVariables["/_p3"].activeChildren[0]; - for (let i = 0; i < 2; i++) { - cy.get( - cesc2( - `#${ - stateVariables[aslist1.componentName] - .activeChildren[i].componentName - }`, - ), - ) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`q+${i + 1}`); - }); - cy.get( - cesc2( - `#${ - stateVariables[aslist2.componentName] - .activeChildren[i].componentName - }`, - ), - ) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`q+${i + 1}`); - }); - cy.get( - cesc2( - `#${ - stateVariables[aslist3.componentName] - .activeChildren[i].componentName - }`, - ), - ) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`q+${i + 1}`); - }); - } - - // Note: put in another .then so test execute in order they appear here - // (so easier to find test results) - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_aslist1"].activeChildren.map( - (x) => x.componentType, - ), - ).eqls(["math", "math"]); - expect( - stateVariables["/_aslist2"].activeChildren.map( - (x) => x.componentType, - ), - ).eqls(["math", "math"]); - expect( - stateVariables[ - stateVariables["/_p3"].activeChildren[0].componentName - ].activeChildren.map((x) => x.componentType), - ).eqls(["math", "math"]); - expect( - stateVariables["/_aslist1"].activeChildren.map( - (x) => - stateVariables[x.componentName].stateValues.value, - ), - ).eqls([ - ["+", "q", 1], - ["+", "q", 2], - ]); - expect( - stateVariables["/_aslist2"].activeChildren.map( - (x) => - stateVariables[x.componentName].stateValues.value, - ), - ).eqls([ - ["+", "q", 1], - ["+", "q", 2], - ]); - expect( - stateVariables[ - stateVariables["/_p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => - stateVariables[x.componentName].stateValues.value, - ), - ).eqls([ - ["+", "q", 1], - ["+", "q", 2], - ]); - }); - }); - - cy.log("set m to -1"); - cy.get(cesc("#\\/m") + " textarea").type(`{end}{backspace}-1{enter}`, { - force: true, - }); - cy.get(cesc("#\\/m2")).should("contain.text", "−1"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let aslist1 = stateVariables["/_p1"].activeChildren[0]; - let aslist2 = stateVariables["/_p2"].activeChildren[0]; - let aslist3 = stateVariables["/_p3"].activeChildren[0]; - for (let i = 0; i < 2; i++) { - cy.get( - cesc2( - `#${ - stateVariables[aslist1.componentName] - .activeChildren[i].componentName - }`, - ), - ) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${i}`); - }); - cy.get( - cesc2( - `#${ - stateVariables[aslist2.componentName] - .activeChildren[i].componentName - }`, - ), - ) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${i}`); - }); - cy.get( - cesc2( - `#${ - stateVariables[aslist3.componentName] - .activeChildren[i].componentName - }`, - ), - ) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${i}`); - }); - } - - // Note: put in another .then so test execute in order they appear here - // (so easier to find test results) - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_aslist1"].activeChildren.map( - (x) => x.componentType, - ), - ).eqls(["math", "math"]); - expect( - stateVariables["/_aslist2"].activeChildren.map( - (x) => x.componentType, - ), - ).eqls(["math", "math"]); - expect( - stateVariables[ - stateVariables["/_p3"].activeChildren[0].componentName - ].activeChildren.map((x) => x.componentType), - ).eqls(["math", "math"]); - expect( - stateVariables["/_aslist1"].activeChildren.map( - (x) => - stateVariables[x.componentName].stateValues.value, - ), - ).eqls([0, 1]); - expect( - stateVariables["/_aslist2"].activeChildren.map( - (x) => - stateVariables[x.componentName].stateValues.value, - ), - ).eqls([0, 1]); - expect( - stateVariables[ - stateVariables["/_p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => - stateVariables[x.componentName].stateValues.value, - ), - ).eqls([0, 1]); - }); - }); - - cy.log("increase n to 5"); - cy.get(cesc("#\\/n") + " textarea").type(`{end}{backspace}5{enter}`, { - force: true, - }); - cy.get(cesc("#\\/n2")).should("contain.text", "5"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let aslist1 = stateVariables["/_p1"].activeChildren[0]; - let aslist2 = stateVariables["/_p2"].activeChildren[0]; - let aslist3 = stateVariables["/_p3"].activeChildren[0]; - for (let i = 0; i < 5; i++) { - cy.get( - cesc2( - `#${ - stateVariables[aslist1.componentName] - .activeChildren[i].componentName - }`, - ), - ) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${i}`); - }); - cy.get( - cesc2( - `#${ - stateVariables[aslist2.componentName] - .activeChildren[i].componentName - }`, - ), - ) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${i}`); - }); - cy.get( - cesc2( - `#${ - stateVariables[aslist3.componentName] - .activeChildren[i].componentName - }`, - ), - ) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(`${i}`); - }); - } - - // Note: put in another .then so test execute in order they appear here - // (so easier to find test results) - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_aslist1"].activeChildren.map( - (x) => x.componentType, - ), - ).eqls(["math", "math", "math", "math", "math"]); - expect( - stateVariables["/_aslist2"].activeChildren.map( - (x) => x.componentType, - ), - ).eqls(["math", "math", "math", "math", "math"]); - expect( - stateVariables[ - stateVariables["/_p3"].activeChildren[0].componentName - ].activeChildren.map((x) => x.componentType), - ).eqls(["math", "math", "math", "math", "math"]); - expect( - stateVariables["/_aslist1"].activeChildren.map( - (x) => - stateVariables[x.componentName].stateValues.value, - ), - ).eqls([0, 1, 2, 3, 4]); - expect( - stateVariables["/_aslist2"].activeChildren.map( - (x) => - stateVariables[x.componentName].stateValues.value, - ), - ).eqls([0, 1, 2, 3, 4]); - expect( - stateVariables[ - stateVariables["/_p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => - stateVariables[x.componentName].stateValues.value, - ), - ).eqls([0, 1, 2, 3, 4]); - }); - }); - }); - - // not sure if this is desired, but it is current behavior - it("extract ignores hide", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

See hidden text: secret

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/_p1")).should("have.text", "See hidden text: secret"); - }); - - it("extracts hide dynamically", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - -

extract 1: hello

-

extract 2: hello

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/e1")).should("have.text", "extract 1: hello"); - cy.get(cesc("#\\/e2")).should("have.text", "extract 2: "); - - cy.get(cesc("#\\/h1")).click(); - cy.get(cesc("#\\/h2")).click(); - - cy.get(cesc("#\\/e1")).should("have.text", "extract 1: "); - cy.get(cesc("#\\/e2")).should("have.text", "extract 2: hello"); - - cy.get(cesc("#\\/h1")).click(); - cy.get(cesc("#\\/h2")).click(); - - cy.get(cesc("#\\/e1")).should("have.text", "extract 1: hello"); - cy.get(cesc("#\\/e2")).should("have.text", "extract 2: "); - }); - - it("extract componentIndex", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

n:

- - - (1,2) - (3,4) - - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let x1 = 1, - y1 = 2, - x2 = 3, - y2 = 4; - - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/Bx") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/Bx") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/Ax"]).eq(undefined); - expect(stateVariables["/al2/Ax"]).eq(undefined); - expect(stateVariables["/Bx"]).eq(undefined); - expect(stateVariables["/al2/Bx"]).eq(undefined); - }); - - cy.log("restrict collection to first component"); - - cy.get(cesc("#\\/n") + " textarea").type("1{enter}", { force: true }); - - cy.get(cesc("#\\/Bx") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/Bx") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/Ax"].stateValues.value).eq(x1); - expect(stateVariables["/al2/Ax"].stateValues.value).eq(x1); - expect(stateVariables["/Bx"]).eq(undefined); - expect(stateVariables["/al2/Bx"]).eq(undefined); - }); - - cy.log("move point"); - cy.window().then(async (win) => { - (x1 = 9), (y1 = -5); - await win.callAction1({ - actionName: "movePoint", - componentName: "/A", - args: { x: x1, y: y1 }, - }); - - cy.get(cesc("#\\/Bx") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/Bx") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/Ax"].stateValues.value).eq(x1); - expect(stateVariables["/al2/Ax"].stateValues.value).eq(x1); - expect(stateVariables["/Bx"]).eq(undefined); - expect(stateVariables["/al2/Bx"]).eq(undefined); - }); - }); - - cy.log("restrict collection to second component"); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/Bx") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/Bx") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/Ax"].stateValues.value).eq(x2); - expect(stateVariables["/al2/Ax"].stateValues.value).eq(x2); - expect(stateVariables["/Bx"]).eq(undefined); - expect(stateVariables["/al2/Bx"]).eq(undefined); - }); - }); - - cy.log("move point"); - cy.window().then(async (win) => { - (x2 = 0), (y2 = 8); - await win.callAction1({ - actionName: "movePoint", - componentName: "/B", - args: { x: x2, y: y2 }, - }); - - cy.get(cesc("#\\/Bx") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/Bx") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/Ax") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/Ax"].stateValues.value).eq(x2); - expect(stateVariables["/al2/Ax"].stateValues.value).eq(x2); - expect(stateVariables["/Bx"]).eq(undefined); - expect(stateVariables["/al2/Bx"]).eq(undefined); - }); - }); - }); - - it("copy propIndex and componentIndex", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

m:

-

n:

- - - (1,2) - (3,4) - - - -

- -

- -

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let x1 = 1, - y1 = 2, - x2 = 3, - y2 = 4; - - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n4") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/n3"]).eq(undefined); - expect(stateVariables["/n4"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); - expect(stateVariables["/al2/n2"]).eq(undefined); - expect(stateVariables["/al2/n3"]).eq(undefined); - expect(stateVariables["/al2/n4"]).eq(undefined); - }); - - cy.log("set propIndex to 1"); - - cy.get(cesc("#\\/n") + " textarea").type("1{enter}", { force: true }); - - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n4") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/n3"]).eq(undefined); - expect(stateVariables["/n4"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); - expect(stateVariables["/al2/n2"]).eq(undefined); - expect(stateVariables["/al2/n3"]).eq(undefined); - expect(stateVariables["/al2/n4"]).eq(undefined); - }); - - cy.log("move point 1"); - cy.window().then(async (win) => { - (x1 = 9), (y1 = -5); - await win.callAction1({ - actionName: "movePoint", - componentName: "/A", - args: { x: x1, y: y1 }, - }); - - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n4") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/n3"]).eq(undefined); - expect(stateVariables["/n4"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); - expect(stateVariables["/al2/n2"]).eq(undefined); - expect(stateVariables["/al2/n3"]).eq(undefined); - expect(stateVariables["/al2/n4"]).eq(undefined); - }); - }); - - cy.log("set componentIndex to 2"); - - cy.get(cesc("#\\/m") + " textarea").type("2{enter}", { force: true }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n4") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(x2); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/n3"]).eq(undefined); - expect(stateVariables["/n4"]).eq(undefined); - expect(stateVariables["/al2/n1"].stateValues.value).eq(x2); - expect(stateVariables["/al2/n2"]).eq(undefined); - expect(stateVariables["/al2/n3"]).eq(undefined); - expect(stateVariables["/al2/n4"]).eq(undefined); - }); - }); - - cy.log("move point2"); - cy.window().then(async (win) => { - (x2 = 0), (y2 = 8); - await win.callAction1({ - actionName: "movePoint", - componentName: "/B", - args: { x: x2, y: y2 }, - }); - - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n4") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(x2); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/n3"]).eq(undefined); - expect(stateVariables["/n4"]).eq(undefined); - expect(stateVariables["/al2/n1"].stateValues.value).eq(x2); - expect(stateVariables["/al2/n2"]).eq(undefined); - expect(stateVariables["/al2/n3"]).eq(undefined); - expect(stateVariables["/al2/n4"]).eq(undefined); - }); - }); - - cy.log("set propIndex to 2"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y2), - ); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y2), - ); - cy.get(cesc("#\\/al2\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n4") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(y2); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/n3"]).eq(undefined); - expect(stateVariables["/n4"]).eq(undefined); - expect(stateVariables["/al2/n1"].stateValues.value).eq(y2); - expect(stateVariables["/al2/n2"]).eq(undefined); - expect(stateVariables["/al2/n3"]).eq(undefined); - expect(stateVariables["/al2/n4"]).eq(undefined); - }); - }); - - cy.log("set componentIndex to 1"); - cy.get(cesc("#\\/m") + " textarea").type("{end}{backspace}1{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y1), - ); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y1), - ); - cy.get(cesc("#\\/al2\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n4") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(y1); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/n3"]).eq(undefined); - expect(stateVariables["/n4"]).eq(undefined); - expect(stateVariables["/al2/n1"].stateValues.value).eq(y1); - expect(stateVariables["/al2/n2"]).eq(undefined); - expect(stateVariables["/al2/n3"]).eq(undefined); - expect(stateVariables["/al2/n4"]).eq(undefined); - }); - }); - - cy.log("set propIndex to 3"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n4") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/n3"]).eq(undefined); - expect(stateVariables["/n4"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); - expect(stateVariables["/al2/n2"]).eq(undefined); - expect(stateVariables["/al2/n3"]).eq(undefined); - expect(stateVariables["/al2/n4"]).eq(undefined); - }); - }); - - cy.log("set propIndex to 1"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}1{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - cy.get(cesc("#\\/al2\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n4") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(x1); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/n3"]).eq(undefined); - expect(stateVariables["/n4"]).eq(undefined); - expect(stateVariables["/al2/n1"].stateValues.value).eq(x1); - expect(stateVariables["/al2/n2"]).eq(undefined); - expect(stateVariables["/al2/n3"]).eq(undefined); - expect(stateVariables["/al2/n4"]).eq(undefined); - }); - }); - - cy.log("set componentIndex to 3"); - cy.get(cesc("#\\/m") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n4") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/n3"]).eq(undefined); - expect(stateVariables["/n4"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); - expect(stateVariables["/al2/n2"]).eq(undefined); - expect(stateVariables["/al2/n3"]).eq(undefined); - expect(stateVariables["/al2/n4"]).eq(undefined); - }); - }); - - cy.log("set componentIndex to 2"); - cy.get(cesc("#\\/m") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/al2\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n4") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"].stateValues.value).eq(x2); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/n3"]).eq(undefined); - expect(stateVariables["/n4"]).eq(undefined); - expect(stateVariables["/al2/n1"].stateValues.value).eq(x2); - expect(stateVariables["/al2/n2"]).eq(undefined); - expect(stateVariables["/al2/n3"]).eq(undefined); - expect(stateVariables["/al2/n4"]).eq(undefined); - }); - }); - - cy.log("clear propIndex"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}{enter}", { - force: true, - }); - - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n4") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n3") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/al2\\/n4") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/A"].stateValues.xs).eqls([x1, y1]); - expect(stateVariables["/B"].stateValues.xs).eqls([x2, y2]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/n3"]).eq(undefined); - expect(stateVariables["/n4"]).eq(undefined); - expect(stateVariables["/al2/n1"]).eq(undefined); - expect(stateVariables["/al2/n2"]).eq(undefined); - expect(stateVariables["/al2/n3"]).eq(undefined); - expect(stateVariables["/al2/n4"]).eq(undefined); - }); - }); - - it("copy multidimensional propIndex", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

m:

-

n:

- - - - - - -

- $pg -

- -

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let x1 = 1, - y1 = 2, - x2 = 3, - y2 = 4, - x3 = -5, - y3 = 6; - - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/p2\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/p2\\/n2") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/pg"].stateValues.vertices).eqls([ - [x1, y1], - [x2, y2], - [x3, y3], - ]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/p2/n1"]).eq(undefined); - expect(stateVariables["/p2/n2"]).eq(undefined); - }); - - cy.log("set second propIndex to 1"); - - cy.get(cesc("#\\/n") + " textarea").type("1{enter}", { force: true }); - - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/p2\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/p2\\/n2") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/pg"].stateValues.vertices).eqls([ - [x1, y1], - [x2, y2], - [x3, y3], - ]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/p2/n1"]).eq(undefined); - expect(stateVariables["/p2/n2"]).eq(undefined); - }); - - cy.log("move first point"); - cy.window().then(async (win) => { - (x1 = 9), (y1 = -5); - await win.callAction1({ - actionName: "movePolygon", - componentName: "/pg", - args: { - pointCoords: { 0: [x1, y1] }, - }, - }); - - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/p2\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/p2\\/n2") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/pg"].stateValues.vertices).eqls([ - [x1, y1], - [x2, y2], - [x3, y3], - ]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/p2/n1"]).eq(undefined); - expect(stateVariables["/p2/n2"]).eq(undefined); - }); - }); - - cy.log("set first propIndex to 2"); - - cy.get(cesc("#\\/m") + " textarea").type("2{enter}", { force: true }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/p2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/p2\\/n2") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/pg"].stateValues.vertices).eqls([ - [x1, y1], - [x2, y2], - [x3, y3], - ]); - expect(stateVariables["/n1"].stateValues.value).eq(x2); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/p2/n1"].stateValues.value).eq(x2); - expect(stateVariables["/p2/n2"]).eq(undefined); - }); - }); - - cy.log("move second point"); - cy.window().then(async (win) => { - (x2 = 0), (y2 = 8); - await win.callAction1({ - actionName: "movePolygon", - componentName: "/pg", - args: { - pointCoords: { 1: [x2, y2] }, - }, - }); - - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/p2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x2), - ); - cy.get(cesc("#\\/p2\\/n2") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/pg"].stateValues.vertices).eqls([ - [x1, y1], - [x2, y2], - [x3, y3], - ]); - expect(stateVariables["/n1"].stateValues.value).eq(x2); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/p2/n1"].stateValues.value).eq(x2); - expect(stateVariables["/p2/n2"]).eq(undefined); - }); - }); - - cy.log("set second propIndex to 2"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y2), - ); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/p2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y2), - ); - cy.get(cesc("#\\/p2\\/n2") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/pg"].stateValues.vertices).eqls([ - [x1, y1], - [x2, y2], - [x3, y3], - ]); - expect(stateVariables["/n1"].stateValues.value).eq(y2); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/p2/n1"].stateValues.value).eq(y2); - expect(stateVariables["/p2/n2"]).eq(undefined); - }); - }); - - cy.log("set first propIndex to 1"); - cy.get(cesc("#\\/m") + " textarea").type("{end}{backspace}1{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y1), - ); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/p2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(y1), - ); - cy.get(cesc("#\\/p2\\/n2") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/pg"].stateValues.vertices).eqls([ - [x1, y1], - [x2, y2], - [x3, y3], - ]); - expect(stateVariables["/n1"].stateValues.value).eq(y1); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/p2/n1"].stateValues.value).eq(y1); - expect(stateVariables["/p2/n2"]).eq(undefined); - }); - }); - - cy.log("set second propIndex to 3"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/p2\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/p2\\/n2") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/pg"].stateValues.vertices).eqls([ - [x1, y1], - [x2, y2], - [x3, y3], - ]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/p2/n1"]).eq(undefined); - expect(stateVariables["/p2/n2"]).eq(undefined); - }); - }); - - cy.log("set second propIndex to 1"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}1{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/p2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x1), - ); - cy.get(cesc("#\\/p2\\/n2") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/pg"].stateValues.vertices).eqls([ - [x1, y1], - [x2, y2], - [x3, y3], - ]); - expect(stateVariables["/n1"].stateValues.value).eq(x1); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/p2/n1"].stateValues.value).eq(x1); - expect(stateVariables["/p2/n2"]).eq(undefined); - }); - }); - - cy.log("set first propindex to 4"); - cy.get(cesc("#\\/m") + " textarea").type("{end}{backspace}4{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/p2\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/p2\\/n2") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/pg"].stateValues.vertices).eqls([ - [x1, y1], - [x2, y2], - [x3, y3], - ]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/p2/n1"]).eq(undefined); - expect(stateVariables["/p2/n2"]).eq(undefined); - }); - }); - - cy.log("set first propIndex to 3"); - cy.get(cesc("#\\/m") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - - cy.window().then(async (win) => { - cy.get(cesc("#\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x3), - ); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/p2\\/n1") + " .mjx-mrow").should( - "contain.text", - nInDOM(x3), - ); - cy.get(cesc("#\\/p2\\/n2") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/pg"].stateValues.vertices).eqls([ - [x1, y1], - [x2, y2], - [x3, y3], - ]); - expect(stateVariables["/n1"].stateValues.value).eq(x3); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/p2/n1"].stateValues.value).eq(x3); - expect(stateVariables["/p2/n2"]).eq(undefined); - }); - }); - - cy.log("clear second propIndex"); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}{enter}", { - force: true, - }); - - cy.get(cesc("#\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/n2") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/p2\\/n1") + " .mjx-mrow").should("not.exist"); - cy.get(cesc("#\\/p2\\/n2") + " .mjx-mrow").should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/pg"].stateValues.vertices).eqls([ - [x1, y1], - [x2, y2], - [x3, y3], - ]); - expect(stateVariables["/n1"]).eq(undefined); - expect(stateVariables["/n2"]).eq(undefined); - expect(stateVariables["/p2/n1"]).eq(undefined); - expect(stateVariables["/p2/n2"]).eq(undefined); - }); - }); - - it("extract is case insensitive", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x - y - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log(`check properties`); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/e1"].stateValues.value).eq("x"); - expect(stateVariables["/e2"].stateValues.value).eq("y"); - }); - }); - - it("createComponentOfType adapts result", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - (1/2,2/3) - (3/4,4/5) - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/e1") + " .mjx-mrow").should("contain.text", "12"); - cy.get(cesc("#\\/e2")).should("have.text", "0.75"); - - cy.log(`check properties`); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/e1"].stateValues.value).eqls(["/", 1, 2]); - expect(stateVariables["/e2"].stateValues.value).eq(0.75); - }); - }); - - it("fail gracefully if omit prop", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

Nothing here: x

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_p1")).should("have.text", "Nothing here: "); - - cy.window().then(async (win) => { - let errorWarnings = await win.returnErrorWarnings1(); - - expect(errorWarnings.errors.length).eq(0); - expect(errorWarnings.warnings.length).eq(1); - - expect(errorWarnings.warnings[0].message).contain( - "Invalid extract. Must have a prop", - ); - expect(errorWarnings.warnings[0].level).eq(1); - expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(2); - expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(22); - expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(2); - expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(54); - }); - }); -}); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/function.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/function.cy.js index 90c388410..126c145d8 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/function.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/function.cy.js @@ -1,10753 +1,9 @@ -import me from "math-expressions"; -import { cesc, cesc2, createFunctionFromDefinition } from "@doenet/utils"; +import { cesc } from "@doenet/utils"; -function nInDOM(n) { - if (n < 0) { - return `−${Math.abs(n)}`; - } else { - return String(n); - } -} - -describe("Function Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("function with nothing", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(0)).closeTo(0, 1e-12); - expect(f(1)).closeTo(0, 1e-12); - expect(f(2)).closeTo(0, 1e-12); - expect(f(-1)).closeTo(0, 1e-12); - expect(f(-2)).closeTo(0, 1e-12); - }); - }); - - it("function with single minimum as number", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(0)).closeTo(2, 1e-12); - expect(f(1)).closeTo(2 + 1, 1e-12); - expect(f(2)).closeTo(2 + 4, 1e-12); - expect(f(-1)).closeTo(2 + 1, 1e-12); - expect(f(-2)).closeTo(2 + 4, 1e-12); - }); - }); - - it("function with single minimum as half-empty tuple", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(0)).closeTo(2, 1e-12); - expect(f(1)).closeTo(2 + 1, 1e-12); - expect(f(2)).closeTo(2 + 4, 1e-12); - expect(f(-1)).closeTo(2 + 1, 1e-12); - expect(f(-2)).closeTo(2 + 4, 1e-12); - }); - }); - - it("function with single minimum as half-empty tuple (no space)", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(0)).closeTo(2, 1e-12); - expect(f(1)).closeTo(2 + 1, 1e-12); - expect(f(2)).closeTo(2 + 4, 1e-12); - expect(f(-1)).closeTo(2 + 1, 1e-12); - expect(f(-2)).closeTo(2 + 4, 1e-12); - }); - }); - - it("function with single minimum, change x-scale", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(0)).closeTo(2, 1e-12); - expect(f(3)).closeTo(2 + 1, 1e-12); - expect(f(6)).closeTo(2 + 4, 1e-12); - expect(f(-3)).closeTo(2 + 1, 1e-12); - expect(f(-6)).closeTo(2 + 4, 1e-12); - }); - }); - - it("function with single minimum, change x-scale and y-scale", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(0)).closeTo(2, 1e-12); - expect(f(3)).closeTo(2 + 1 * 5, 1e-12); - expect(f(6)).closeTo(2 + 4 * 5, 1e-12); - expect(f(-3)).closeTo(2 + 1 * 5, 1e-12); - expect(f(-6)).closeTo(2 + 4 * 5, 1e-12); - }); - }); - - it("function with single maximum", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(0)).closeTo(3, 1e-12); - expect(f(1)).closeTo(3 - 1, 1e-12); - expect(f(2)).closeTo(3 - 4, 1e-12); - expect(f(-1)).closeTo(3 - 1, 1e-12); - expect(f(-2)).closeTo(3 - 4, 1e-12); - }); - }); - - it("function with single maximum, change x-scale", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(0)).closeTo(3, 1e-12); - expect(f(3)).closeTo(3 - 1, 1e-12); - expect(f(6)).closeTo(3 - 4, 1e-12); - expect(f(-3)).closeTo(3 - 1, 1e-12); - expect(f(-6)).closeTo(3 - 4, 1e-12); - }); - }); - - it("function with single maximum, change x-scale and y-scale", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(0)).closeTo(3, 1e-12); - expect(f(3)).closeTo(3 - 1 * 5, 1e-12); - expect(f(6)).closeTo(3 - 4 * 5, 1e-12); - expect(f(-3)).closeTo(3 - 1 * 5, 1e-12); - expect(f(-6)).closeTo(3 - 4 * 5, 1e-12); - }); - }); - - it("function with single minimum, specify location as half-empty tuple", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(0)).closeTo(4, 1e-12); - expect(f(1)).closeTo(1, 1e-12); - expect(f(2)).closeTo(0, 1e-12); - expect(f(3)).closeTo(1, 1e-12); - expect(f(4)).closeTo(4, 1e-12); - }); - }); - - it("function with single minimum, specify location as half-empty tuple (no space)", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(0)).closeTo(4, 1e-12); - expect(f(1)).closeTo(1, 1e-12); - expect(f(2)).closeTo(0, 1e-12); - expect(f(3)).closeTo(1, 1e-12); - expect(f(4)).closeTo(4, 1e-12); - }); - }); - - it("function with single minimum, specify location and value as tuple", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(0)).closeTo(4 - 3, 1e-12); - expect(f(1)).closeTo(1 - 3, 1e-12); - expect(f(2)).closeTo(0 - 3, 1e-12); - expect(f(3)).closeTo(1 - 3, 1e-12); - expect(f(4)).closeTo(4 - 3, 1e-12); - }); - }); - - it("function with single extremum, specify location and value as tuple", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(0)).closeTo(-4 - 3, 1e-12); - expect(f(1)).closeTo(-1 - 3, 1e-12); - expect(f(2)).closeTo(0 - 3, 1e-12); - expect(f(3)).closeTo(-1 - 3, 1e-12); - expect(f(4)).closeTo(-4 - 3, 1e-12); - }); - }); - - it("function with min and max", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(0)).closeTo(0, 1e-12); - expect(f(1)).closeTo(1, 1e-12); - expect(f(0.5)).closeTo(0.5, 1e-12); - // like parabola to left of minimum - expect(f(-1)).closeTo(1, 1e-12); - expect(f(-2)).closeTo(4, 1e-12); - expect(f(-3)).closeTo(9, 1e-12); - // like parabola to right of maximum - expect(f(2)).closeTo(0, 1e-12); - expect(f(3)).closeTo(-3, 1e-12); - expect(f(4)).closeTo(-8, 1e-12); - }); - }); - - it("function with min and extremum", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(0)).closeTo(0, 1e-12); - expect(f(1)).closeTo(1, 1e-12); - expect(f(0.5)).closeTo(0.5, 1e-12); - // like parabola to left of minimum - expect(f(-1)).closeTo(1, 1e-12); - expect(f(-2)).closeTo(4, 1e-12); - expect(f(-3)).closeTo(9, 1e-12); - // like parabola to right of maximum - expect(f(2)).closeTo(0, 1e-12); - expect(f(3)).closeTo(-3, 1e-12); - expect(f(4)).closeTo(-8, 1e-12); - }); - }); - - it("function with extremum and max", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(0)).closeTo(0, 1e-12); - expect(f(1)).closeTo(1, 1e-12); - expect(f(0.5)).closeTo(0.5, 1e-12); - // like parabola to left of minimum - expect(f(-1)).closeTo(1, 1e-12); - expect(f(-2)).closeTo(4, 1e-12); - expect(f(-3)).closeTo(9, 1e-12); - // like parabola to right of maximum - expect(f(2)).closeTo(0, 1e-12); - expect(f(3)).closeTo(-3, 1e-12); - expect(f(4)).closeTo(-8, 1e-12); - }); - }); - - it("function two extrema, same height", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(0)).closeTo(0, 1e-12); - expect(f(1)).closeTo(0, 1e-12); - expect(f(0.5)).closeTo(-1, 1e-12); - // like parabola to left of maximum - expect(f(-1)).closeTo(-1, 1e-12); - expect(f(-2)).closeTo(-4, 1e-12); - expect(f(-3)).closeTo(-9, 1e-12); - // like parabola to right of maximum - expect(f(2)).closeTo(-1, 1e-12); - expect(f(3)).closeTo(-4, 1e-12); - expect(f(4)).closeTo(-9, 1e-12); - }); - }); - - it("function two extrema, second higher", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(0)).closeTo(0, 1e-12); - expect(f(1)).closeTo(2, 1e-12); - expect(f(0.5)).closeTo(1, 1e-12); - // like parabola to left of minimum - expect(f(-1)).closeTo(1, 1e-12); - expect(f(-2)).closeTo(4, 1e-12); - expect(f(-3)).closeTo(9, 1e-12); - // like parabola to right of maximum - expect(f(2)).closeTo(1, 1e-12); - expect(f(3)).closeTo(-2, 1e-12); - expect(f(4)).closeTo(-7, 1e-12); - }); - }); - - it("function two extrema, second lower", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(0)).closeTo(0, 1e-12); - expect(f(1)).closeTo(-2, 1e-12); - expect(f(0.5)).closeTo(-1, 1e-12); - // like parabola to left of maximum - expect(f(-1)).closeTo(-1, 1e-12); - expect(f(-2)).closeTo(-4, 1e-12); - expect(f(-3)).closeTo(-9, 1e-12); - // like parabola to right of minimum - expect(f(2)).closeTo(-1, 1e-12); - expect(f(3)).closeTo(2, 1e-12); - expect(f(4)).closeTo(7, 1e-12); - }); - }); - - it("function with two minima", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(-2)).closeTo(1, 1e-12); - expect(f(2)).closeTo(1, 1e-12); - expect(f(0)).closeTo(2, 1e-12); - // like parabola to left of minimum - expect(f(-3)).closeTo(1 + 1, 1e-12); - expect(f(-4)).closeTo(4 + 1, 1e-12); - expect(f(-5)).closeTo(9 + 1, 1e-12); - // like parabola to right of minimum - expect(f(3)).closeTo(1 + 1, 1e-12); - expect(f(4)).closeTo(4 + 1, 1e-12); - expect(f(5)).closeTo(9 + 1, 1e-12); - }); - }); - - it("function with two minima and maximum with specified height", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(-2)).closeTo(1, 1e-12); - expect(f(2)).closeTo(1, 1e-12); - expect(f(0)).closeTo(5, 1e-12); - // like parabola to left of minimum - expect(f(-3)).closeTo(1 + 1, 1e-12); - expect(f(-4)).closeTo(4 + 1, 1e-12); - expect(f(-5)).closeTo(9 + 1, 1e-12); - // like parabola to right of minimum - expect(f(3)).closeTo(1 + 1, 1e-12); - expect(f(4)).closeTo(4 + 1, 1e-12); - expect(f(5)).closeTo(9 + 1, 1e-12); - }); - }); - - it("function with two minima and extremum with specified height", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(-2)).closeTo(1, 1e-12); - expect(f(2)).closeTo(1, 1e-12); - expect(f(0)).closeTo(5, 1e-12); - // like parabola to left of minimum - expect(f(-3)).closeTo(1 + 1, 1e-12); - expect(f(-4)).closeTo(4 + 1, 1e-12); - expect(f(-5)).closeTo(9 + 1, 1e-12); - // like parabola to right of minimum - expect(f(3)).closeTo(1 + 1, 1e-12); - expect(f(4)).closeTo(4 + 1, 1e-12); - expect(f(5)).closeTo(9 + 1, 1e-12); - }); - }); - - it("function with maximum and higher minimum", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(-2)).closeTo(1, 1e-12); - expect(f(-3)).closeTo(0, 1e-12); - expect(f(-2 + 4 / 3)).closeTo(0, 1e-12); - - expect(f(2)).closeTo(2, 1e-12); - expect(f(3)).closeTo(3, 1e-12); - expect(f(2 - 4 / 3)).closeTo(3, 1e-12); - - expect(f(0)).closeTo(1.5, 1e-12); - }); - }); - - it("function with maximum and higher extremum", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(-2)).closeTo(1, 1e-12); - expect(f(-3)).closeTo(0, 1e-12); - expect(f(0)).closeTo(0, 1e-12); - - expect(f(2)).closeTo(2, 1e-12); - expect(f(3)).closeTo(1, 1e-12); - }); - }); - - it("function with minimum and lower maximum", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(-2)).closeTo(3, 1e-12); - expect(f(-3)).closeTo(4, 1e-12); - expect(f(-2 + 4 / 3)).closeTo(4, 1e-12); - - expect(f(2)).closeTo(2, 1e-12); - expect(f(3)).closeTo(1, 1e-12); - expect(f(2 - 4 / 3)).closeTo(1, 1e-12); - - expect(f(0)).closeTo(2.5, 1e-12); - }); - }); - - it("function with minimum and lower extremum", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(-2)).closeTo(3, 1e-12); - expect(f(-3)).closeTo(4, 1e-12); - expect(f(0)).closeTo(4, 1e-12); - - expect(f(2)).closeTo(2, 1e-12); - expect(f(3)).closeTo(3, 1e-12); - }); - }); - - it("function with extremum and lower maximum", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(-2)).closeTo(3, 1e-12); - expect(f(-3)).closeTo(2, 1e-12); - expect(f(0)).closeTo(1, 1e-12); - - expect(f(2)).closeTo(2, 1e-12); - expect(f(3)).closeTo(1, 1e-12); - }); - }); - - it("functions with copied extrema that overwrite attributes", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(3)).closeTo(-2, 1e-12); - expect(f(5)).closeTo(-2, 1e-12); - - expect(f(2)).closeTo(-3, 1e-12); - expect(f(4)).closeTo(-3, 1e-12); - expect(f(6)).closeTo(-3, 1e-12); - - let g = createFunctionFromDefinition( - stateVariables["/_function2"].stateValues.fDefinitions[0], - ); - expect(g(3)).closeTo(2, 1e-12); - expect(g(5)).closeTo(-2, 1e-12); - - expect(g(2)).closeTo(1, 1e-12); - expect(g(4)).closeTo(0, 1e-12); - expect(g(6)).closeTo(-1, 1e-12); - }); - }); - - it("copy function and overwrite extrema", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/f"].stateValues.fDefinitions[0], - ); - expect(f(2)).closeTo(3, 1e-12); - expect(f(4)).closeTo(4, 1e-12); - - expect(f(1)).closeTo(4, 1e-12); - expect(f(3)).closeTo(3.5, 1e-12); - expect(f(5)).closeTo(3, 1e-12); - - let g = createFunctionFromDefinition( - stateVariables["/g"].stateValues.fDefinitions[0], - ); - expect(g(0)).closeTo(4, 1e-12); - expect(g(2)).closeTo(3, 1e-12); - - expect(g(-1)).closeTo(3, 1e-12); - expect(g(1)).closeTo(3.5, 1e-12); - expect(g(3)).closeTo(4, 1e-12); - - let h = createFunctionFromDefinition( - stateVariables["/h"].stateValues.fDefinitions[0], - ); - expect(h(4)).closeTo(4, 1e-12); - expect(h(6)).closeTo(3, 1e-12); - - expect(h(3)).closeTo(3, 1e-12); - expect(h(5)).closeTo(3.5, 1e-12); - expect(h(7)).closeTo(4, 1e-12); - }); - }); - - it("function with maximum through points", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(-2)).closeTo(2, 1e-12); - expect(f(-5)).closeTo(0, 1e-12); - expect(f(-6)).closeTo(-1, 1e-12); - - // extrapolates linearly - let slope = f(-6) - f(-7); - expect(f(-8)).closeTo(-1 - slope * 2, 1e-12); - expect(f(-9)).closeTo(-1 - slope * 3, 1e-12); - expect(f(-10)).closeTo(-1 - slope * 4, 1e-12); - - expect(f(0)).closeTo(0, 1e-12); - expect(f(1)).closeTo(0, 1e-12); - // extrapolates linearly - expect(f(2)).closeTo(0, 1e-12); - expect(f(3)).closeTo(0, 1e-12); - }); - }); - - it("function with single through point", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(-6)).closeTo(-1, 1e-12); - expect(f(-2)).closeTo(-1, 1e-12); - expect(f(-12)).closeTo(-1, 1e-12); - expect(f(12)).closeTo(-1, 1e-12); - }); - }); - - it("function with single through point with slope", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(-6)).closeTo(-1, 1e-12); - expect(f(-2)).closeTo(-1 + 3 * (-2 + 6), 1e-12); - expect(f(-12)).closeTo(-1 + 3 * (-12 + 6), 1e-12); - expect(f(12)).closeTo(-1 + 3 * (12 + 6), 1e-12); - }); - }); - - it("function with single through point with dynamic slope", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

slope:

- - - -

$_mathinput1.value{assignNames="m1"}

- `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/m1")).should("contain.text", "\uff3f"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(-6)).closeTo(-1, 1e-12); - expect(f(-2)).closeTo(-1 + 0 * (-2 + 6), 1e-12); - expect(f(-12)).closeTo(-1 + 0 * (-12 + 6), 1e-12); - expect(f(12)).closeTo(-1 + 0 * (12 + 6), 1e-12); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type("2{enter}", { - force: true, - }); - cy.get(cesc("#\\/m1")).should("contain.text", "2"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(-6)).closeTo(-1, 1e-12); - expect(f(-2)).closeTo(-1 + 2 * (-2 + 6), 1e-12); - expect(f(-12)).closeTo(-1 + 2 * (-12 + 6), 1e-12); - expect(f(12)).closeTo(-1 + 2 * (12 + 6), 1e-12); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{end}{backspace}-3{enter}", - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "−3"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(-6)).closeTo(-1, 1e-12); - expect(f(-2)).closeTo(-1 - 3 * (-2 + 6), 1e-12); - expect(f(-12)).closeTo(-1 - 3 * (-12 + 6), 1e-12); - expect(f(12)).closeTo(-1 - 3 * (12 + 6), 1e-12); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea") - .type("{end}{backspace}{backspace}", { force: true }) - .blur(); - cy.get(cesc("#\\/m1")).should("contain.text", "_"); - cy.wait(100); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(-6)).closeTo(-1, 1e-12); - expect(f(-2)).closeTo(-1 + 0 * (-2 + 6), 1e-12); - expect(f(-12)).closeTo(-1 + 0 * (-12 + 6), 1e-12); - expect(f(12)).closeTo(-1 + 0 * (12 + 6), 1e-12); - }); - }); - - it("function with two through points with dynamic slope", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

slope:

- - - -

$_mathinput1.value{assignNames="m1"}

- `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.log("with undefined slope, get line through points"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(-6)).closeTo(-1, 1e-12); - expect(f(-2)).closeTo(-1 + 1 * (-2 + 6), 1e-12); - expect(f(-12)).closeTo(-1 + 1 * (-12 + 6), 1e-12); - expect(f(12)).closeTo(-1 + 1 * (12 + 6), 1e-12); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type("2{enter}", { - force: true, - }); - cy.get(cesc("#\\/m1")).should("contain.text", "2"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(-6 - 0.01)).closeTo(-1 - 0.01 * 2, 1e-3); - expect(f(-6)).closeTo(-1, 1e-12); - expect(f(-6 + 0.01)).closeTo(-1 + 0.01 * 2, 1e-3); - - expect(f(3 - 0.01)).closeTo(8 - 0.01 * 2, 1e-3); - expect(f(3)).closeTo(8, 1e-12); - expect(f(3 + 0.01)).closeTo(8 + 0.01 * 2, 1e-3); - - // extrapolate linearly - expect(f(-6 - 3)).closeTo(-1 - 3 * 2, 1e-12); - expect(f(3 + 3)).closeTo(8 + 3 * 2, 1e-12); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{end}{backspace}-3{enter}", - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "−3"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(-6 - 0.01)).closeTo(-1 - 0.01 * -3, 1e-3); - expect(f(-6)).closeTo(-1, 1e-12); - expect(f(-6 + 0.01)).closeTo(-1 + 0.01 * -3, 1e-3); - - expect(f(3 - 0.01)).closeTo(8 - 0.01 * -3, 1e-3); - expect(f(3)).closeTo(8, 1e-12); - expect(f(3 + 0.01)).closeTo(8 + 0.01 * -3, 1e-3); - - // extrapolate linearly - expect(f(-6 - 3)).closeTo(-1 - 3 * -3, 1e-12); - expect(f(3 + 3)).closeTo(8 + 3 * -3, 1e-12); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea") - .type("{end}{backspace}{backspace}", { force: true }) - .blur(); - cy.get(cesc("#\\/m1")).should("contain.text", "_"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(-6)).closeTo(-1, 1e-12); - expect(f(-2)).closeTo(-1 + 1 * (-2 + 6), 1e-12); - expect(f(-12)).closeTo(-1 + 1 * (-12 + 6), 1e-12); - expect(f(12)).closeTo(-1 + 1 * (12 + 6), 1e-12); - }); - }); - - it("function through three points", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(0)).closeTo(2, 1e-12); - expect(f(2)).closeTo(1, 1e-12); - expect(f(3)).closeTo(2, 1e-12); - // extrapolate linearly - let slope = f(4) - f(3); - expect(f(5)).closeTo(2 + slope * 2, 1e-12); - expect(f(6)).closeTo(2 + slope * 3, 1e-12); - expect(f(7)).closeTo(2 + slope * 4, 1e-12); - slope = f(0) - f(-1); - expect(f(-2)).closeTo(2 - slope * 2, 1e-12); - expect(f(-3)).closeTo(2 - slope * 3, 1e-12); - expect(f(-4)).closeTo(2 - slope * 4, 1e-12); - }); - }); - - it("function through three points, label with math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(0)).closeTo(2, 1e-12); - expect(f(2)).closeTo(1, 1e-12); - expect(f(3)).closeTo(2, 1e-12); - // extrapolate linearly - let slope = f(4) - f(3); - expect(f(5)).closeTo(2 + slope * 2, 1e-12); - expect(f(6)).closeTo(2 + slope * 3, 1e-12); - expect(f(7)).closeTo(2 + slope * 4, 1e-12); - slope = f(0) - f(-1); - expect(f(-2)).closeTo(2 - slope * 2, 1e-12); - expect(f(-3)).closeTo(2 - slope * 3, 1e-12); - expect(f(-4)).closeTo(2 - slope * 4, 1e-12); - - expect(stateVariables["/_function1"].stateValues.label).eq( - "\\(\\int f\\)", - ); - }); - }); - - it("function through three points with slopes", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (2,1) - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(-0.01)).closeTo(2 - 0.01 * 0.5, 1e-3); - expect(f(0)).closeTo(2, 1e-12); - expect(f(0.01)).closeTo(2 + 0.01 * 0.5, 1e-3); - - expect(f(2 - 0.01)).closeTo(1 - 0.01 * 2, 1e-3); - expect(f(2)).closeTo(1, 1e-12); - expect(f(2 + 0.01)).closeTo(1 + 0.01 * 2, 1e-3); - - expect(f(3 - 0.01)).closeTo(2 - 0.01 * -1, 1e-3); - expect(f(3)).closeTo(2, 1e-12); - expect(f(3 + 0.01)).closeTo(2 + 0.01 * -1, 1e-3); - - // extrapolate linearly - let slope = -1; - expect(f(5)).closeTo(2 + slope * 2, 1e-12); - expect(f(6)).closeTo(2 + slope * 3, 1e-12); - expect(f(7)).closeTo(2 + slope * 4, 1e-12); - slope = 0.5; - expect(f(-2)).closeTo(2 - slope * 2, 1e-12); - expect(f(-3)).closeTo(2 - slope * 3, 1e-12); - expect(f(-4)).closeTo(2 - slope * 4, 1e-12); - }); - }); - - it("function with conflicting points", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - assert.isNaN(f(0)); - assert.isNaN(f(1)); - assert.isNaN(f(2)); - }); - - cy.window().then(async (win) => { - let errorWarnings = await win.returnErrorWarnings1(); - - expect(errorWarnings.errors.length).eq(0); - expect(errorWarnings.warnings.length).eq(1); - - expect(errorWarnings.warnings[0].message).contain( - `Function contains two points with locations too close together. Can't define function`, - ); - expect(errorWarnings.warnings[0].level).eq(1); - expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(4); - expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(5); - expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(4); - expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(44); - }); - }); - - it("function with non-numerical points and slope", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - let fleft = (x) => 6 - (x - 5) ** 2 / 4; - let fright = (x) => 6 - (x - 5) ** 2; - expect(f(5)).closeTo(6, 1e-12); - expect(f(1)).closeTo(2, 1e-12); - expect(f(-2)).closeTo(fleft(-2), 1e-12); - expect(f(7)).closeTo(fright(7), 1e-12); - }); - - cy.window().then(async (win) => { - let errorWarnings = await win.returnErrorWarnings1(); - - expect(errorWarnings.errors.length).eq(0); - expect(errorWarnings.warnings.length).eq(5); - - expect(errorWarnings.warnings[0].message).contain( - `Ignoring non-numerical maximum of function`, - ); - expect(errorWarnings.warnings[0].level).eq(1); - expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(4); - expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(5); - expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(4); - expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(109); - - expect(errorWarnings.warnings[1].message).contain( - `Ignoring non-numerical minimum of function`, - ); - expect(errorWarnings.warnings[1].level).eq(1); - expect(errorWarnings.warnings[1].doenetMLrange.lineBegin).eq(4); - expect(errorWarnings.warnings[1].doenetMLrange.charBegin).eq(5); - expect(errorWarnings.warnings[1].doenetMLrange.lineEnd).eq(4); - expect(errorWarnings.warnings[1].doenetMLrange.charEnd).eq(109); - - expect(errorWarnings.warnings[2].message).contain( - `Ignoring non-numerical extremum of function`, - ); - expect(errorWarnings.warnings[2].level).eq(1); - expect(errorWarnings.warnings[2].doenetMLrange.lineBegin).eq(4); - expect(errorWarnings.warnings[2].doenetMLrange.charBegin).eq(5); - expect(errorWarnings.warnings[2].doenetMLrange.lineEnd).eq(4); - expect(errorWarnings.warnings[2].doenetMLrange.charEnd).eq(109); - - expect(errorWarnings.warnings[3].message).contain( - `Ignoring non-numerical slope of function`, - ); - expect(errorWarnings.warnings[3].level).eq(1); - expect(errorWarnings.warnings[3].doenetMLrange.lineBegin).eq(4); - expect(errorWarnings.warnings[3].doenetMLrange.charBegin).eq(5); - expect(errorWarnings.warnings[3].doenetMLrange.lineEnd).eq(4); - expect(errorWarnings.warnings[3].doenetMLrange.charEnd).eq(109); - - expect(errorWarnings.warnings[4].message).contain( - `Ignoring non-numerical point of function`, - ); - expect(errorWarnings.warnings[4].level).eq(1); - expect(errorWarnings.warnings[4].doenetMLrange.lineBegin).eq(4); - expect(errorWarnings.warnings[4].doenetMLrange.charBegin).eq(5); - expect(errorWarnings.warnings[4].doenetMLrange.lineEnd).eq(4); - expect(errorWarnings.warnings[4].doenetMLrange.charEnd).eq(109); - }); - }); - - it("function with empty maximum", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - let factual = (x) => (x - 4) ** 2; - expect(f(4)).closeTo(0, 1e-12); - expect(f(-2)).closeTo(factual(-2), 1e-12); - expect(f(7)).closeTo(factual(7), 1e-12); - }); - - cy.window().then(async (win) => { - let errorWarnings = await win.returnErrorWarnings1(); - - expect(errorWarnings.errors.length).eq(0); - expect(errorWarnings.warnings.length).eq(1); - - expect(errorWarnings.warnings[0].message).contain( - `Ignoring empty maximum of function`, - ); - expect(errorWarnings.warnings[0].level).eq(1); - expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(4); - expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(7); - expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(4); - expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(45); - }); - }); - - it("copy function and overwrite through points and slopes", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/f"].stateValues.fDefinitions[0], - ); - expect(f(0)).closeTo(2, 1e-12); - expect(f(2)).closeTo(1, 1e-12); - expect(f(3)).closeTo(2, 1e-12); - // extrapolate linearly - let slope = f(4) - f(3); - expect(f(5)).closeTo(2 + slope * 2, 1e-12); - expect(f(6)).closeTo(2 + slope * 3, 1e-12); - expect(f(7)).closeTo(2 + slope * 4, 1e-12); - slope = f(0) - f(-1); - expect(f(-2)).closeTo(2 - slope * 2, 1e-12); - expect(f(-3)).closeTo(2 - slope * 3, 1e-12); - expect(f(-4)).closeTo(2 - slope * 4, 1e-12); - - let g = createFunctionFromDefinition( - stateVariables["/g"].stateValues.fDefinitions[0], - ); - expect(g(1)).closeTo(5, 1e-12); - expect(g(4)).closeTo(2, 1e-12); - // linear function - slope = g(1) - g(0); - expect(g(2)).closeTo(5 + slope * 1, 1e-12); - expect(g(3)).closeTo(5 + slope * 2, 1e-12); - expect(g(4)).closeTo(5 + slope * 3, 1e-12); - expect(g(0)).closeTo(5 + slope * -1, 1e-12); - expect(g(-1)).closeTo(5 + slope * -2, 1e-12); - expect(g(-2)).closeTo(5 + slope * -3, 1e-12); - - let h = createFunctionFromDefinition( - stateVariables["/h"].stateValues.fDefinitions[0], - ); - expect(h(0)).closeTo(2, 1e-12); - expect(h(2)).closeTo(1, 1e-12); - expect(h(3)).closeTo(2, 1e-12); - // extrapolate linearly at given slopes - slope = -3; - expect(h(5)).closeTo(2 + slope * 2, 1e-12); - expect(h(6)).closeTo(2 + slope * 3, 1e-12); - expect(h(7)).closeTo(2 + slope * 4, 1e-12); - slope = 1; - expect(h(-2)).closeTo(2 - slope * 2, 1e-12); - expect(h(-3)).closeTo(2 - slope * 3, 1e-12); - expect(h(-4)).closeTo(2 - slope * 4, 1e-12); - // close to given slope near middle point - slope = 2; - expect(h(2.0001)).closeTo(1 + slope * 0.0001, 1e-7); - expect(h(1.9999)).closeTo(1 + slope * -0.0001, 1e-7); - }); - }); - - it("check monotonicity", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - for (let x = -5; x <= 6; x += 0.1) { - expect(f(x - 0.1)).lessThan(f(x)); - } - expect(f(-5)).closeTo(0, 1e-12); - expect(f(-4)).closeTo(0.1, 1e-12); - expect(f(-3)).closeTo(0.3, 1e-12); - expect(f(-2)).closeTo(3, 1e-12); - expect(f(-1)).closeTo(3.1, 1e-12); - expect(f(0)).closeTo(3.2, 1e-12); - expect(f(1)).closeTo(5, 1e-12); - expect(f(6)).closeTo(6, 1e-12); - expect(f(7)).closeTo(5, 1e-12); - expect(f(8)).closeTo(2, 1e-12); - }); - }); - - it("point constrained to function", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - $_function1 - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let p = stateVariables["/_point1"]; - - let x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - let y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); - - expect(6 - ((x - 5) * (x - 5)) / 25).closeTo(y, 1e-5); - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: -8, y: 8 }, - }); - - stateVariables = await win.returnAllStateVariables1(); - - p = stateVariables["/_point1"]; - - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); - - expect(6 - ((x - 5) * (x - 5)) / 25).closeTo(y, 1e-5); - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 8, y: 8 }, - }); - - stateVariables = await win.returnAllStateVariables1(); - - p = stateVariables["/_point1"]; - - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); - - expect(6 - (x - 5) * (x - 5) * (2 / 9)).closeTo(y, 1e-5); - }); - }); - - it("point constrained to function, symbolic initial x", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - x^2 - - - - $f - - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let p = stateVariables["/_point1"]; - - expect( - me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(), - ).closeTo(Math.sqrt(2), 1e-6); - expect( - me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(), - ).closeTo(2, 1e-6); - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: -2, y: 2 }, - }); - - stateVariables = await win.returnAllStateVariables1(); - - p = stateVariables["/_point1"]; - - 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); - }); - }); - - it("point constrained to function, restrict to closed domain", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - $_function1 - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let p = stateVariables["/_point1"]; - - let x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - let y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); - - expect(x).closeTo(1, 1e-12); - expect(6 - ((x - 5) * (x - 5)) / 25).closeTo(y, 1e-5); - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: -8, y: 8 }, - }); - - stateVariables = await win.returnAllStateVariables1(); - - p = stateVariables["/_point1"]; - - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); - - expect(x).closeTo(-4, 1e-12); - expect(6 - ((x - 5) * (x - 5)) / 25).closeTo(y, 1e-5); - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 6, y: 8 }, - }); - - stateVariables = await win.returnAllStateVariables1(); - - p = stateVariables["/_point1"]; - - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); - - expect(x).closeTo(6, 1e-12); - expect(6 - (x - 5) * (x - 5) * (2 / 9)).closeTo(y, 1e-5); - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 8, y: -4 }, - }); - - stateVariables = await win.returnAllStateVariables1(); - - p = stateVariables["/_point1"]; - - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); - - expect(x).closeTo(7, 1e-12); - expect(6 - (x - 5) * (x - 5) * (2 / 9)).closeTo(y, 1e-5); - }); - }); - - it("point constrained to function, restrict to open domain", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - $_function1 - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let p = stateVariables["/_point1"]; - - let x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - let y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); - - expect(x).closeTo(1, 1e-12); - expect(6 - ((x - 5) * (x - 5)) / 25).closeTo(y, 1e-5); - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: -8, y: 8 }, - }); - - stateVariables = await win.returnAllStateVariables1(); - - p = stateVariables["/_point1"]; - - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); - - expect(x).greaterThan(-4 + 1e-12); - expect(x).lessThan(-4 + 1e-3); - expect(6 - ((x - 5) * (x - 5)) / 25).closeTo(y, 1e-5); - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 6, y: 8 }, - }); - - stateVariables = await win.returnAllStateVariables1(); - - p = stateVariables["/_point1"]; - - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); - - expect(x).closeTo(6, 1e-12); - expect(6 - (x - 5) * (x - 5) * (2 / 9)).closeTo(y, 1e-5); - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 8, y: -4 }, - }); - - stateVariables = await win.returnAllStateVariables1(); - - p = stateVariables["/_point1"]; - - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); - - expect(x).lessThan(7 - 1e-12); - expect(x).greaterThan(7 - 1e-3); - expect(6 - (x - 5) * (x - 5) * (2 / 9)).closeTo(y, 1e-5); - }); - }); - - it("point constrained to function with restricted domain, not explicit", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - sqrt(x)sqrt(5-x) - - - - $f - - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - let f = (x) => Math.sqrt(x) * Math.sqrt(5 - x); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let p = stateVariables["/_point1"]; - 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); - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: -1, y: 8 }, - }); - - stateVariables = await win.returnAllStateVariables1(); - - p = stateVariables["/_point1"]; - - let x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - let y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); - - expect(y).closeTo(f(x), 1e-6); - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 6, y: 8 }, - }); - - stateVariables = await win.returnAllStateVariables1(); - - p = stateVariables["/_point1"]; - - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); - - expect(y).closeTo(f(x), 1e-6); - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 8, y: -4 }, - }); - - stateVariables = await win.returnAllStateVariables1(); - - p = stateVariables["/_point1"]; - - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); - - expect(y).closeTo(f(x), 1e-6); - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: -1, y: -6 }, - }); - - stateVariables = await win.returnAllStateVariables1(); - - p = stateVariables["/_point1"]; - - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); - - expect(y).closeTo(f(x), 1e-6); - }); - }); - - it("function determined by formula via sugar", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - 3/(1+e^(-x/2)) - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_function1"].stateValues.numInputs).eq(1); - - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - // let numericalf = (stateVariables['/_function1'].stateValues.numericalfs)[0]; - // let symbolicf = (stateVariables['/_function1'].stateValues.symbolicfs)[0]; - - expect(f(-5)).closeTo(3 / (1 + Math.exp(5 / 2)), 1e-12); - expect(f(1)).closeTo(3 / (1 + Math.exp(-1 / 2)), 1e-12); - // expect(numericalf(-5)).closeTo(3 / (1 + Math.exp(5 / 2)), 1E-12); - // expect(numericalf(1)).closeTo(3 / (1 + Math.exp(-1 / 2)), 1E-12); - // expect(symbolicf(-5).equals(me.fromText('3/(1+e^(5/2))'))).eq(true) - // expect(symbolicf(1).equals(me.fromText('3/(1+e^(-1/2))'))).eq(true) - // expect(symbolicf('z').equals(me.fromText('3/(1+e^(-z/2))'))).eq(true) - }); - }); - - it("function determined by formula via sugar, label with math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - 3/(1+e^(-x/2)) - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_function1"].stateValues.numInputs).eq(1); - - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - - expect(f(-5)).closeTo(3 / (1 + Math.exp(5 / 2)), 1e-12); - expect(f(1)).closeTo(3 / (1 + Math.exp(-1 / 2)), 1e-12); - - expect(stateVariables["/_function1"].stateValues.label).eq( - "Hello \\(\\frac{3}{1 + e^{-\\frac{x}{2}}}\\)", - ); - }); - }); - - it("function determined by formula via sugar, with strings and macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - $a/(1+e^(-x/$b)) - - - 3 - 2 - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_function1"].stateValues.numInputs).eq(1); - - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - // let numericalf = (stateVariables['/_function1'].stateValues.numericalfs)[0]; - // let symbolicf = (stateVariables['/_function1'].stateValues.symbolicfs)[0]; - - expect(f(-5)).closeTo(3 / (1 + Math.exp(5 / 2)), 1e-12); - expect(f(1)).closeTo(3 / (1 + Math.exp(-1 / 2)), 1e-12); - // expect(numericalf(-5)).closeTo(3 / (1 + Math.exp(5 / 2)), 1E-12); - // expect(numericalf(1)).closeTo(3 / (1 + Math.exp(-1 / 2)), 1E-12); - // expect(symbolicf(-5).equals(me.fromText('3/(1+e^(5/2))'))).eq(true) - // expect(symbolicf(1).equals(me.fromText('3/(1+e^(-1/2))'))).eq(true) - // expect(symbolicf('z').equals(me.fromText('3/(1+e^(-z/2))'))).eq(true) - }); - }); - - it("function determined by formula via sugar, with strings and maths", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - 3/(1+e^(-x/2)) - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_function1"].stateValues.numInputs).eq(1); - - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - // let numericalf = (stateVariables['/_function1'].stateValues.numericalfs)[0]; - // let symbolicf = (stateVariables['/_function1'].stateValues.symbolicfs)[0]; - - expect(f(-5)).closeTo(3 / (1 + Math.exp(5 / 2)), 1e-12); - expect(f(1)).closeTo(3 / (1 + Math.exp(-1 / 2)), 1e-12); - // expect(numericalf(-5)).closeTo(3 / (1 + Math.exp(5 / 2)), 1E-12); - // expect(numericalf(1)).closeTo(3 / (1 + Math.exp(-1 / 2)), 1E-12); - // expect(symbolicf(-5).equals(me.fromText('3/(1+e^(5/2))'))).eq(true) - // expect(symbolicf(1).equals(me.fromText('3/(1+e^(-1/2))'))).eq(true) - // expect(symbolicf('z').equals(me.fromText('3/(1+e^(-z/2))'))).eq(true) - }); - }); - - it("function determined by formula via sugar, with strings and copies", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - $a/(1+e^(-x/$b)) - - - 3 - 2 - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_function1"].stateValues.numInputs).eq(1); - - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - // let numericalf = (stateVariables['/_function1'].stateValues.numericalfs)[0]; - // let symbolicf = (stateVariables['/_function1'].stateValues.symbolicfs)[0]; - - expect(f(-5)).closeTo(3 / (1 + Math.exp(5 / 2)), 1e-12); - expect(f(1)).closeTo(3 / (1 + Math.exp(-1 / 2)), 1e-12); - // expect(numericalf(-5)).closeTo(3 / (1 + Math.exp(5 / 2)), 1E-12); - // expect(numericalf(1)).closeTo(3 / (1 + Math.exp(-1 / 2)), 1E-12); - // expect(symbolicf(-5).equals(me.fromText('3/(1+e^(5/2))'))).eq(true) - // expect(symbolicf(1).equals(me.fromText('3/(1+e^(-1/2))'))).eq(true) - // expect(symbolicf('z').equals(me.fromText('3/(1+e^(-z/2))'))).eq(true) - }); - }); - - it("function determined by math formula", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - 3/(1+e^(-x/2)) - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_function1"].stateValues.numInputs).eq(1); - - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - // let numericalf = (stateVariables['/_function1'].stateValues.numericalfs)[0]; - // let symbolicf = (stateVariables['/_function1'].stateValues.symbolicfs)[0]; - - expect(f(-5)).closeTo(3 / (1 + Math.exp(5 / 2)), 1e-12); - expect(f(1)).closeTo(3 / (1 + Math.exp(-1 / 2)), 1e-12); - // expect(numericalf(-5)).closeTo(3 / (1 + Math.exp(5 / 2)), 1E-12); - // expect(numericalf(1)).closeTo(3 / (1 + Math.exp(-1 / 2)), 1E-12); - // expect(symbolicf(-5).equals(me.fromText('3/(1+e^(5/2))'))).eq(true) - // expect(symbolicf(1).equals(me.fromText('3/(1+e^(-1/2))'))).eq(true) - // expect(symbolicf('z').equals(me.fromText('3/(1+e^(-z/2))'))).eq(true) - }); - }); - - it("function determined by math formula, label with math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - 3/(1+e^(-x/2)) - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_function1"].stateValues.numInputs).eq(1); - - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - - expect(f(-5)).closeTo(3 / (1 + Math.exp(5 / 2)), 1e-12); - expect(f(1)).closeTo(3 / (1 + Math.exp(-1 / 2)), 1e-12); - - expect(stateVariables["/_function1"].stateValues.label).eq( - "Hello \\(\\frac{3}{1 + e^{-\\frac{x}{2}}}\\)", - ); - }); - }); - - it("function determined by math formula, with explicit copy tags", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - $a/(1+e^(-x/$b)) - - - 3 - 2 - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_function1"].stateValues.numInputs).eq(1); - - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - // let numericalf = (stateVariables['/_function1'].stateValues.numericalfs)[0]; - // let symbolicf = (stateVariables['/_function1'].stateValues.symbolicfs)[0]; - - expect(f(-5)).closeTo(3 / (1 + Math.exp(5 / 2)), 1e-12); - expect(f(1)).closeTo(3 / (1 + Math.exp(-1 / 2)), 1e-12); - // expect(numericalf(-5)).closeTo(3 / (1 + Math.exp(5 / 2)), 1E-12); - // expect(numericalf(1)).closeTo(3 / (1 + Math.exp(-1 / 2)), 1E-12); - // expect(symbolicf(-5).equals(me.fromText('3/(1+e^(5/2))'))).eq(true) - // expect(symbolicf(1).equals(me.fromText('3/(1+e^(-1/2))'))).eq(true) - // expect(symbolicf('z').equals(me.fromText('3/(1+e^(-z/2))'))).eq(true) - }); - }); - - it("symbolic function determined by formula via sugar", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - 3/(1+e^(-x/2)) - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let numericalf = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - // let numericalf = (stateVariables['/_function1'].stateValues.numericalfs)[0]; - // let symbolicf = (stateVariables['/_function1'].stateValues.symbolicfs)[0]; - - // expect(f(-5).equals(me.fromText('3/(1+e^(5/2))'))).eq(true) - // expect(f(1).equals(me.fromText('3/(1+e^(-1/2))'))).eq(true) - // expect(f('z').equals(me.fromText('3/(1+e^(-z/2))'))).eq(true) - expect( - me - .fromAst(stateVariables["/fz"].stateValues.value) - .equals(me.fromText("3/(1+e^(-z/2))")), - ).eq(true); - expect(numericalf(-5)).closeTo(3 / (1 + Math.exp(5 / 2)), 1e-12); - expect(numericalf(1)).closeTo(3 / (1 + Math.exp(-1 / 2)), 1e-12); - // expect(symbolicf(-5).equals(me.fromText('3/(1+e^(5/2))'))).eq(true) - // expect(symbolicf(1).equals(me.fromText('3/(1+e^(-1/2))'))).eq(true) - // expect(symbolicf('z').equals(me.fromText('3/(1+e^(-z/2))'))).eq(true) - }); - }); - - it("symbolic function determined by formula via sugar, with strings and macro", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - 3/(1+e^(-$var/2)) - - - x - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let numericalf = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - // let numericalf = (stateVariables['/_function1'].stateValues.numericalfs)[0]; - // let symbolicf = (stateVariables['/_function1'].stateValues.symbolicfs)[0]; - - // expect(f(-5).equals(me.fromText('3/(1+e^(5/2))'))).eq(true) - // expect(f(1).equals(me.fromText('3/(1+e^(-1/2))'))).eq(true) - // expect(f('z').equals(me.fromText('3/(1+e^(-z/2))'))).eq(true) - expect( - me - .fromAst(stateVariables["/fz"].stateValues.value) - .equals(me.fromText("3/(1+e^(-z/2))")), - ).eq(true); - expect(numericalf(-5)).closeTo(3 / (1 + Math.exp(5 / 2)), 1e-12); - expect(numericalf(1)).closeTo(3 / (1 + Math.exp(-1 / 2)), 1e-12); - // expect(symbolicf(-5).equals(me.fromText('3/(1+e^(5/2))'))).eq(true) - // expect(symbolicf(1).equals(me.fromText('3/(1+e^(-1/2))'))).eq(true) - // expect(symbolicf('z').equals(me.fromText('3/(1+e^(-z/2))'))).eq(true) - }); - }); - - it("symbolic function determined by math formula", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - 3/(1+e^(-x/2)) - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let numericalf = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - // let numericalf = (stateVariables['/_function1'].stateValues.numericalfs)[0]; - // let symbolicf = (stateVariables['/_function1'].stateValues.symbolicfs)[0]; - - // expect(f(-5).equals(me.fromText('3/(1+e^(5/2))'))).eq(true) - // expect(f(1).equals(me.fromText('3/(1+e^(-1/2))'))).eq(true) - // expect(f('z').equals(me.fromText('3/(1+e^(-z/2))'))).eq(true) - expect( - me - .fromAst(stateVariables["/fz"].stateValues.value) - .equals(me.fromText("3/(1+e^(-z/2))")), - ).eq(true); - expect(numericalf(-5)).closeTo(3 / (1 + Math.exp(5 / 2)), 1e-12); - expect(numericalf(1)).closeTo(3 / (1 + Math.exp(-1 / 2)), 1e-12); - // expect(symbolicf(-5).equals(me.fromText('3/(1+e^(5/2))'))).eq(true) - // expect(symbolicf(1).equals(me.fromText('3/(1+e^(-1/2))'))).eq(true) - }); - }); - - it("function determined by sugar formula in different variable", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - q^2 sin(pi q/2)/100 - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - // let numericalf = (stateVariables['/_function1'].stateValues.numericalfs)[0]; - // let symbolicf = (stateVariables['/_function1'].stateValues.symbolicfs)[0]; - - expect(f(-5)).closeTo( - (25 * Math.sin(0.5 * Math.PI * -5)) / 100, - 1e-12, - ); - expect(f(3)).closeTo( - (9 * Math.sin(0.5 * Math.PI * 3)) / 100, - 1e-12, - ); - // expect(numericalf(-5)).closeTo(25 * Math.sin(0.5 * Math.PI * (-5)) / 100, 1E-12); - // expect(numericalf(3)).closeTo(9 * Math.sin(0.5 * Math.PI * (3)) / 100, 1E-12); - // expect(symbolicf(-5).equals(me.fromText('(-5)^2sin(pi(-5)/2)/100'))).eq(true) - // expect(symbolicf(3).equals(me.fromText('(3)^2sin(pi(3)/2)/100'))).eq(true) - // expect(symbolicf('p').equals(me.fromText('p^2sin(pi p/2)/100'))).eq(true) - }); - }); - - it("function determined by sugar formula in different variable, with strings and macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - $var^$c sin(pi $var/$c)/$d - - - - q - 2 - 100 - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - // let numericalf = (stateVariables['/_function1'].stateValues.numericalfs)[0]; - // let symbolicf = (stateVariables['/_function1'].stateValues.symbolicfs)[0]; - - expect(f(-5)).closeTo( - (25 * Math.sin(0.5 * Math.PI * -5)) / 100, - 1e-12, - ); - expect(f(3)).closeTo( - (9 * Math.sin(0.5 * Math.PI * 3)) / 100, - 1e-12, - ); - // expect(numericalf(-5)).closeTo(25 * Math.sin(0.5 * Math.PI * (-5)) / 100, 1E-12); - // expect(numericalf(3)).closeTo(9 * Math.sin(0.5 * Math.PI * (3)) / 100, 1E-12); - // expect(symbolicf(-5).equals(me.fromText('(-5)^2sin(pi(-5)/2)/100'))).eq(true) - // expect(symbolicf(3).equals(me.fromText('(3)^2sin(pi(3)/2)/100'))).eq(true) - // expect(symbolicf('p').equals(me.fromText('p^2sin(pi p/2)/100'))).eq(true) - }); - }); - - it("function determined by math formula in different variable", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - q^2 sin(pi q/2)/100 - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - // let numericalf = (stateVariables['/_function1'].stateValues.numericalfs)[0]; - // let symbolicf = (stateVariables['/_function1'].stateValues.symbolicfs)[0]; - - expect(f(-5)).closeTo( - (25 * Math.sin(0.5 * Math.PI * -5)) / 100, - 1e-12, - ); - expect(f(3)).closeTo( - (9 * Math.sin(0.5 * Math.PI * 3)) / 100, - 1e-12, - ); - // expect(numericalf(-5)).closeTo(25 * Math.sin(0.5 * Math.PI * (-5)) / 100, 1E-12); - // expect(numericalf(3)).closeTo(9 * Math.sin(0.5 * Math.PI * (3)) / 100, 1E-12); - // expect(symbolicf(-5).equals(me.fromText('(-5)^2sin(pi(-5)/2)/100'))).eq(true) - // expect(symbolicf(3).equals(me.fromText('(3)^2sin(pi(3)/2)/100'))).eq(true) - // expect(symbolicf('p').equals(me.fromText('p^2sin(pi p/2)/100'))).eq(true) - }); - }); - - it("function with empty variables attribute", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - x^2 sin(pi x/2)/100 - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - // let numericalf = (stateVariables['/_function1'].stateValues.numericalfs)[0]; - // let symbolicf = (stateVariables['/_function1'].stateValues.symbolicfs)[0]; - - expect(f(-5)).closeTo( - (25 * Math.sin(0.5 * Math.PI * -5)) / 100, - 1e-12, - ); - expect(f(3)).closeTo( - (9 * Math.sin(0.5 * Math.PI * 3)) / 100, - 1e-12, - ); - // expect(numericalf(-5)).closeTo(25 * Math.sin(0.5 * Math.PI * (-5)) / 100, 1E-12); - // expect(numericalf(3)).closeTo(9 * Math.sin(0.5 * Math.PI * (3)) / 100, 1E-12); - // expect(symbolicf(-5).equals(me.fromText('(-5)^2sin(pi(-5)/2)/100'))).eq(true) - // expect(symbolicf(3).equals(me.fromText('(3)^2sin(pi(3)/2)/100'))).eq(true) - // expect(symbolicf('p').equals(me.fromText('p^2sin(pi p/2)/100'))).eq(true) - }); - }); - - it("warnings for bad variable or variable attribute", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x - x - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let errorWarnings = await win.returnErrorWarnings1(); - - expect(errorWarnings.errors.length).eq(0); - expect(errorWarnings.warnings.length).eq(2); - - expect(errorWarnings.warnings[0].message).contain( - `Invalid value of a variable: cos(x)`, - ); - expect(errorWarnings.warnings[0].level).eq(1); - expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(4); - expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(25); - expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(4); - expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(30); - - expect(errorWarnings.warnings[1].message).contain( - `Invalid value of a variable: sin(x)`, - ); - expect(errorWarnings.warnings[1].level).eq(1); - expect(errorWarnings.warnings[1].doenetMLrange.lineBegin).eq(3); - expect(errorWarnings.warnings[1].doenetMLrange.charBegin).eq(26); - expect(errorWarnings.warnings[1].doenetMLrange.lineEnd).eq(3); - expect(errorWarnings.warnings[1].doenetMLrange.charEnd).eq(31); - }); - }); - - it("function determined by function", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - q^2 sin(pi q/2)/100 - - - $_function1 - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function2"].stateValues.fDefinitions[0], - ); - // let numericalf = (stateVariables['/_function2'].stateValues.numericalfs)[0]; - // let symbolicf = (stateVariables['/_function2'].stateValues.symbolicfs)[0]; - - expect(f(-5)).closeTo( - (25 * Math.sin(0.5 * Math.PI * -5)) / 100, - 1e-12, - ); - expect(f(3)).closeTo( - (9 * Math.sin(0.5 * Math.PI * 3)) / 100, - 1e-12, - ); - // expect(numericalf(-5)).closeTo(25 * Math.sin(0.5 * Math.PI * (-5)) / 100, 1E-12); - // expect(numericalf(3)).closeTo(9 * Math.sin(0.5 * Math.PI * (3)) / 100, 1E-12); - // expect(symbolicf(-5).equals(me.fromText('(-5)^2sin(pi(-5)/2)/100'))).eq(true) - // expect(symbolicf(3).equals(me.fromText('(3)^2sin(pi(3)/2)/100'))).eq(true) - // expect(symbolicf('p').equals(me.fromText('p^2sin(pi p/2)/100'))).eq(true) - }); - }); - - it("function determined by function, label with math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - q^2 sin(pi q/2)/100 - - - $_function1 - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function2"].stateValues.fDefinitions[0], - ); - - expect(f(-5)).closeTo( - (25 * Math.sin(0.5 * Math.PI * -5)) / 100, - 1e-12, - ); - expect(f(3)).closeTo( - (9 * Math.sin(0.5 * Math.PI * 3)) / 100, - 1e-12, - ); - - expect( - stateVariables["/_function2"].stateValues.label - .replaceAll("\\,", "") - .replaceAll(" ", ""), - ).eq( - "\\(\\frac{q^{2}\\sin\\left(\\frac{\\piq}{2}\\right)}{100}\\)", - ); - }); - }); - - it("point constrained to function in different variable", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - log(2u) - - - - $_function1 - - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let p = stateVariables["/_point1"]; - - let x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - let y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); - - expect(Math.log(2 * x)).closeTo(y, 1e-5); - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 8, y: 8 }, - }); - - stateVariables = await win.returnAllStateVariables1(); - - p = stateVariables["/_point1"]; - - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); - - expect(Math.log(2 * x)).closeTo(y, 1e-5); - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: -8, y: -8 }, - }); - - stateVariables = await win.returnAllStateVariables1(); - - p = stateVariables["/_point1"]; - - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); - - expect(Math.log(2 * x)).closeTo(y, 1e-5); - }); - }); - - it("point constrained to function in different variable, restrict left-open domain", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - log(2u) - - - - $_function1 - - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let p = stateVariables["/_point1"]; - - let x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - let y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); - - expect(x).greaterThan(0.1 + 1e-12); - expect(x).lessThan(0.1 + 1e-3); - expect(Math.log(2 * x)).closeTo(y, 1e-5); - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 4, y: 6 }, - }); - - stateVariables = await win.returnAllStateVariables1(); - - p = stateVariables["/_point1"]; - - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); - - expect(x).closeTo(4, 1e-12); - expect(Math.log(2 * x)).closeTo(y, 1e-5); - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 8, y: 8 }, - }); - - stateVariables = await win.returnAllStateVariables1(); - - p = stateVariables["/_point1"]; - - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); - - expect(x).closeTo(6, 1e-12); - expect(Math.log(2 * x)).closeTo(y, 1e-5); - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: -8, y: -8 }, - }); - - stateVariables = await win.returnAllStateVariables1(); - - p = stateVariables["/_point1"]; - - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); - - expect(x).greaterThan(0.1 + 1e-12); - expect(x).lessThan(0.1 + 1e-3); - expect(Math.log(2 * x)).closeTo(y, 1e-5); - }); - }); - - it("point constrained to function in different variable, restrict right-open domain", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - log(2u) - - - - $_function1 - - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let p = stateVariables["/_point1"]; - - let x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - let y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); - - expect(x).eq(0.1); - expect(Math.log(2 * x)).closeTo(y, 1e-5); - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 4, y: 6 }, - }); - - stateVariables = await win.returnAllStateVariables1(); - - p = stateVariables["/_point1"]; - - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); - - expect(x).closeTo(4, 1e-12); - expect(Math.log(2 * x)).closeTo(y, 1e-5); - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 8, y: 8 }, - }); - - stateVariables = await win.returnAllStateVariables1(); - - p = stateVariables["/_point1"]; - - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); - - expect(x).lessThan(6 - 1e-12); - expect(x).greaterThan(6 - 1e-3); - expect(Math.log(2 * x)).closeTo(y, 1e-5); - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: -8, y: -8 }, - }); - - stateVariables = await win.returnAllStateVariables1(); - - p = stateVariables["/_point1"]; - - x = me.fromAst(p.stateValues.xs[0]).evaluate_to_constant(); - y = me.fromAst(p.stateValues.xs[1]).evaluate_to_constant(); - - expect(x).closeTo(0.1, 1e-12); - expect(Math.log(2 * x)).closeTo(y, 1e-5); - }); - }); - - it("calculated extrema from spline", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (0.7, 5.43) - (3,4) - (5,6) - (-5,6) - - $_function1.maxima - $_function1.minima - - -

Number of maxima:

-

Maxima: $_function1.maxima

-

Number of minima:

-

Minima: $_function1.minima

-

Number of extrema:

-

Extrema: $_function1.extrema

-

Global maximum:

-

Global minimum:

-

Global supremum:

-

Global infimum:

- `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "2"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−2.15,7),(5,6)"); - }); - cy.get(cesc("#\\/numMinima")).should("have.text", "2"); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−5,6),(3,4)"); - }); - cy.get(cesc("#\\/numExtrema")).should("have.text", "4"); - - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−5,6),(−2.15,7),(3,4),(5,6)"); - }); - cy.get(cesc2("#/globalmax")).should("have.text", "NaN"); - cy.get(cesc2("#/globalsup")).should("have.text", "∞"); - cy.get(cesc2("#/globalmin")).should("have.text", "NaN"); - cy.get(cesc2("#/globalinf")).should("have.text", "-∞"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 2, y: 2 }, - }); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "2"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−1.5,7),(5,6)"); - }); - cy.get(cesc("#\\/numMinima")).should("have.text", "2"); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−5,6),(2,2)"); - }); - cy.get(cesc("#\\/numExtrema")).should("have.text", "4"); - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−5,6),(−1.5,7),(2,2),(5,6)"); - }); - cy.get(cesc2("#/globalmax")).should("have.text", "NaN"); - cy.get(cesc2("#/globalsup")).should("have.text", "∞"); - cy.get(cesc2("#/globalmin")).should("have.text", "NaN"); - cy.get(cesc2("#/globalinf")).should("have.text", "-∞"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 3.6, y: 5.1 }, - }); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "3"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−1,7),(3.6,5.1),(5,6)"); - }); - cy.get(cesc("#\\/numMinima")).should("have.text", "3"); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−5,6),(3,4),(4.3,5)"); - }); - cy.get(cesc("#\\/numExtrema")).should("have.text", "6"); - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal( - "(−5,6),(−1,7),(3,4),(3.6,5.1),(4.3,5),(5,6)", - ); - }); - cy.get(cesc2("#/globalmax")).should("have.text", "NaN"); - cy.get(cesc2("#/globalsup")).should("have.text", "∞"); - cy.get(cesc2("#/globalmin")).should("have.text", "NaN"); - cy.get(cesc2("#/globalinf")).should("have.text", "-∞"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 8, y: 9 }, - }); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "2"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−1,7),(5,6)"); - }); - cy.get(cesc("#\\/numMinima")).should("have.text", "3"); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−5,6),(3,4),(6.5,5)"); - }); - cy.get(cesc("#\\/numExtrema")).should("have.text", "5"); - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal( - "(−5,6),(−1,7),(3,4),(5,6),(6.5,5)", - ); - }); - cy.get(cesc2("#/globalmax")).should("have.text", "NaN"); - cy.get(cesc2("#/globalsup")).should("have.text", "∞"); - cy.get(cesc2("#/globalmin")).should("have.text", "4"); - cy.get(cesc2("#/globalinf")).should("have.text", "4"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 5, y: 2 }, - }); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "0"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("_"); - }); - cy.get(cesc("#\\/numMinima")).should("have.text", "0"); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("_"); - }); - cy.get(cesc("#\\/numExtrema")).should("have.text", "0"); - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("_"); - }); - cy.get(cesc2("#/globalmax")).should("have.text", "NaN"); - cy.get(cesc2("#/globalsup")).should("have.text", "NaN"); - cy.get(cesc2("#/globalmin")).should("have.text", "NaN"); - cy.get(cesc2("#/globalinf")).should("have.text", "NaN"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: -9, y: 0 }, - }); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "3"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−7,7),(−1,7),(5,6)"); - }); - cy.get(cesc("#\\/numMinima")).should("have.text", "2"); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−5,6),(3,4)"); - }); - cy.get(cesc("#\\/numExtrema")).should("have.text", "5"); - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal( - "(−7,7),(−5,6),(−1,7),(3,4),(5,6)", - ); - }); - cy.get(cesc2("#/globalmax")).should("have.text", "7"); - cy.get(cesc2("#/globalsup")).should("have.text", "7"); - cy.get(cesc2("#/globalmin")).should("have.text", "NaN"); - cy.get(cesc2("#/globalinf")).should("have.text", "-∞"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point4", - args: { x: 8, y: 3 }, - }); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "1"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,6)"); - }); - cy.get(cesc("#\\/numMinima")).should("have.text", "1"); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(8,3)"); - }); - cy.get(cesc("#\\/numExtrema")).should("have.text", "2"); - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,6),(8,3)"); - }); - cy.get(cesc2("#/globalmax")).should("have.text", "NaN"); - cy.get(cesc2("#/globalsup")).should("have.text", "∞"); - cy.get(cesc2("#/globalmin")).should("have.text", "0"); - cy.get(cesc2("#/globalinf")).should("have.text", "0"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point4", - args: { x: 8, y: 6 }, - }); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "2"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,6),(7,7)"); - }); - cy.get(cesc("#\\/numMinima")).should("have.text", "2"); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(6,5),(8,6)"); - }); - cy.get(cesc("#\\/numExtrema")).should("have.text", "4"); - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,6),(6,5),(7,7),(8,6)"); - }); - cy.get(cesc2("#/globalmax")).should("have.text", "NaN"); - cy.get(cesc2("#/globalsup")).should("have.text", "∞"); - cy.get(cesc2("#/globalmin")).should("have.text", "0"); - cy.get(cesc2("#/globalinf")).should("have.text", "0"); - }); - }); - - it("calculated extrema from spline, restrict to right-open domain", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

xmin = - xmax =

- - (0.7, 5.43) - (3,4) - (5,6) - (-5,6) - - $_function1.maxima - $_function1.minima - - -

Number of maxima:

-

Maxima: $_function1.maxima

-

Number of minima:

-

Minima: $_function1.minima

-

Number of extrema:

-

Extrema: $_function1.extrema

-

Global maximum:

-

Global minimum:

-

Global supremum:

-

Global infimum:

- `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "2"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−2.15,7),(5,6)"); - }); - cy.get(cesc("#\\/numMinima")).should("have.text", "1"); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,4)"); - }); - cy.get(cesc("#\\/numExtrema")).should("have.text", "3"); - - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−2.15,7),(3,4),(5,6)"); - }); - cy.get(cesc2("#/globalmax")).should("have.text", "7"); - cy.get(cesc2("#/globalsup")).should("have.text", "7"); - cy.get(cesc2("#/globalmin")).should("have.text", "NaN"); - cy.get(cesc2("#/globalinf")).should("have.text", "2"); - - cy.get(cesc("#\\/xmin") + " textarea").type( - "{end}{backspace}2{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/xmax") + " textarea").type( - "{end}{backspace}4{enter}", - { - force: true, - }, - ); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "0"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("_"); - }); - cy.get(cesc("#\\/numMinima")).should("have.text", "1"); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,4)"); - }); - cy.get(cesc("#\\/numExtrema")).should("have.text", "1"); - - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,4)"); - }); - cy.get(cesc2("#/globalmax")).should("have.text", "6.99"); - cy.get(cesc2("#/globalsup")).should("have.text", "6.99"); - cy.get(cesc2("#/globalmin")).should("have.text", "4"); - cy.get(cesc2("#/globalinf")).should("have.text", "4"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 2, y: 2 }, - }); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "1"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−1.5,7)"); - }); - cy.get(cesc("#\\/numMinima")).should("have.text", "1"); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,2)"); - }); - cy.get(cesc("#\\/numExtrema")).should("have.text", "2"); - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−1.5,7),(2,2)"); - }); - cy.get(cesc2("#/globalmax")).should("have.text", "7"); - cy.get(cesc2("#/globalsup")).should("have.text", "7"); - cy.get(cesc2("#/globalmin")).should("have.text", "2"); - cy.get(cesc2("#/globalinf")).should("have.text", "2"); - - cy.get(cesc("#\\/xmin") + " textarea").type( - "{end}{backspace}6{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/xmax") + " textarea").type( - "{end}{backspace}8{enter}", - { - force: true, - }, - ); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "2"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−1.5,7),(5,6)"); - }); - cy.get(cesc("#\\/numMinima")).should("have.text", "2"); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−5,6),(2,2)"); - }); - cy.get(cesc("#\\/numExtrema")).should("have.text", "4"); - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−5,6),(−1.5,7),(2,2),(5,6)"); - }); - cy.get(cesc2("#/globalmax")).should("have.text", "7"); - cy.get(cesc2("#/globalsup")).should("have.text", "7"); - cy.get(cesc2("#/globalmin")).should("have.text", "NaN"); - cy.get(cesc2("#/globalinf")).should("have.text", "-3"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 3.6, y: 5.1 }, - }); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "3"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−1,7),(3.6,5.1),(5,6)"); - }); - cy.get(cesc("#\\/numMinima")).should("have.text", "3"); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−5,6),(3,4),(4.3,5)"); - }); - cy.get(cesc("#\\/numExtrema")).should("have.text", "6"); - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal( - "(−5,6),(−1,7),(3,4),(3.6,5.1),(4.3,5),(5,6)", - ); - }); - cy.get(cesc2("#/globalmax")).should("have.text", "7"); - cy.get(cesc2("#/globalsup")).should("have.text", "7"); - cy.get(cesc2("#/globalmin")).should("have.text", "NaN"); - cy.get(cesc2("#/globalinf")).should("have.text", "-3"); - - cy.get(cesc("#\\/xmin") + " textarea").type( - "{end}{backspace}1{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/xmax") + " textarea").type( - "{end}{backspace}4{enter}", - { - force: true, - }, - ); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "2"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−1,7),(3.6,5.1)"); - }); - cy.get(cesc("#\\/numMinima")).should("have.text", "1"); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,4)"); - }); - cy.get(cesc("#\\/numExtrema")).should("have.text", "3"); - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−1,7),(3,4),(3.6,5.1)"); - }); - cy.get(cesc2("#/globalmax")).should("have.text", "7"); - cy.get(cesc2("#/globalsup")).should("have.text", "7"); - cy.get(cesc2("#/globalmin")).should("have.text", "4"); - cy.get(cesc2("#/globalinf")).should("have.text", "4"); - }); - }); - - it("calculated extrema from spline, restrict to left-open domain", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

xmin = - xmax =

- - (0.7, 5.43) - (3,4) - (5,6) - (-5,6) - - $_function1.maxima - $_function1.minima - - -

Number of maxima:

-

Maxima: $_function1.maxima

-

Number of minima:

-

Minima: $_function1.minima

-

Number of extrema:

-

Extrema: $_function1.extrema

-

Global maximum:

-

Global minimum:

-

Global supremum:

-

Global infimum:

- `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "2"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−2.15,7),(5,6)"); - }); - cy.get(cesc("#\\/numMinima")).should("have.text", "1"); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,4)"); - }); - cy.get(cesc("#\\/numExtrema")).should("have.text", "3"); - - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−2.15,7),(3,4),(5,6)"); - }); - cy.get(cesc2("#/globalmax")).should("have.text", "7"); - cy.get(cesc2("#/globalsup")).should("have.text", "7"); - cy.get(cesc2("#/globalmin")).should("have.text", "2"); - cy.get(cesc2("#/globalinf")).should("have.text", "2"); - - cy.get(cesc("#\\/xmin") + " textarea").type( - "{end}{backspace}2{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/xmax") + " textarea").type( - "{end}{backspace}4{enter}", - { - force: true, - }, - ); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "0"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("_"); - }); - cy.get(cesc("#\\/numMinima")).should("have.text", "1"); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,4)"); - }); - cy.get(cesc("#\\/numExtrema")).should("have.text", "1"); - - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,4)"); - }); - cy.get(cesc2("#/globalmax")).should("have.text", "NaN"); - cy.get(cesc2("#/globalsup")).should("have.text", "6.99"); - cy.get(cesc2("#/globalmin")).should("have.text", "4"); - cy.get(cesc2("#/globalinf")).should("have.text", "4"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 2, y: 2 }, - }); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "1"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−1.5,7)"); - }); - cy.get(cesc("#\\/numMinima")).should("have.text", "1"); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,2)"); - }); - cy.get(cesc("#\\/numExtrema")).should("have.text", "2"); - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−1.5,7),(2,2)"); - }); - cy.get(cesc2("#/globalmax")).should("have.text", "7"); - cy.get(cesc2("#/globalsup")).should("have.text", "7"); - cy.get(cesc2("#/globalmin")).should("have.text", "2"); - cy.get(cesc2("#/globalinf")).should("have.text", "2"); - - cy.get(cesc("#\\/xmin") + " textarea").type( - "{end}{backspace}6{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/xmax") + " textarea").type( - "{end}{backspace}8{enter}", - { - force: true, - }, - ); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "2"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−1.5,7),(5,6)"); - }); - cy.get(cesc("#\\/numMinima")).should("have.text", "2"); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−5,6),(2,2)"); - }); - cy.get(cesc("#\\/numExtrema")).should("have.text", "4"); - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−5,6),(−1.5,7),(2,2),(5,6)"); - }); - cy.get(cesc2("#/globalmax")).should("have.text", "7"); - cy.get(cesc2("#/globalsup")).should("have.text", "7"); - cy.get(cesc2("#/globalmin")).should("have.text", "-3"); - cy.get(cesc2("#/globalinf")).should("have.text", "-3"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 3.6, y: 5.1 }, - }); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "3"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−1,7),(3.6,5.1),(5,6)"); - }); - cy.get(cesc("#\\/numMinima")).should("have.text", "3"); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−5,6),(3,4),(4.3,5)"); - }); - cy.get(cesc("#\\/numExtrema")).should("have.text", "6"); - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal( - "(−5,6),(−1,7),(3,4),(3.6,5.1),(4.3,5),(5,6)", - ); - }); - cy.get(cesc2("#/globalmax")).should("have.text", "7"); - cy.get(cesc2("#/globalsup")).should("have.text", "7"); - cy.get(cesc2("#/globalmin")).should("have.text", "-3"); - cy.get(cesc2("#/globalinf")).should("have.text", "-3"); - - cy.get(cesc("#\\/xmin") + " textarea").type( - "{end}{backspace}1{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/xmax") + " textarea").type( - "{end}{backspace}4{enter}", - { - force: true, - }, - ); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "1"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3.6,5.1)"); - }); - cy.get(cesc("#\\/numMinima")).should("have.text", "1"); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,4)"); - }); - cy.get(cesc("#\\/numExtrema")).should("have.text", "2"); - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,4),(3.6,5.1)"); - }); - cy.get(cesc2("#/globalmax")).should("have.text", "NaN"); - cy.get(cesc2("#/globalsup")).should("have.text", "7"); - cy.get(cesc2("#/globalmin")).should("have.text", "4"); - cy.get(cesc2("#/globalinf")).should("have.text", "4"); - }); - }); - - it("calculated extrema from spline, restrict domain, just through points", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (0, 0) - (2, -1.8) - (5,-4) - (7,0) - (8,1) - - $_function1.maxima - $_function1.minima - - -

Number of maxima:

-

Maxima: $_function1.maxima

-

Number of minima:

-

Minima: $_function1.minima

-

Number of extrema:

-

Extrema: $_function1.extrema

-

Global maximum:

-

Global minimum:

-

Global supremum:

-

Global infimum:

- `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - // it is set up so that minimum of quadratic interpolating between first two points - // is past maximum of domain - // check for bug where this stopped looking for minima - cy.get(cesc("#\\/numMaxima")).should("have.text", "0"); - cy.get(cesc("#\\/numMinima")).should("have.text", "1"); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,−4)"); - }); - cy.get(cesc("#\\/numExtrema")).should("have.text", "1"); - - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,−4)"); - }); - - cy.get(cesc2("#/globalmax")).should("have.text", "NaN"); - cy.get(cesc2("#/globalsup")).should("have.text", "2.33"); - cy.get(cesc2("#/globalmin")).should("have.text", "-4"); - cy.get(cesc2("#/globalinf")).should("have.text", "-4"); - - cy.window().then(async (win) => { - // now move points so that the minimum of the cubic interpolating between - // the first two points is past maximum of the domain - // check for bug where this stopped looking for minima - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 0, y: -0.35 }, - }); - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point2", - args: { x: 1.8, y: -1.36 }, - }); - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point5", - args: { x: 1, y: -0.866 }, - }); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "0"); - cy.get(cesc("#\\/numMinima")).should("have.text", "1"); - cy.get(cesc("#\\/_math2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,−4)"); - }); - cy.get(cesc("#\\/numExtrema")).should("have.text", "1"); - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,−4)"); - }); - cy.get(cesc2("#/globalmax")).should("have.text", "NaN"); - cy.get(cesc2("#/globalsup")).should("have.text", "12"); - cy.get(cesc2("#/globalmin")).should("have.text", "-4"); - cy.get(cesc2("#/globalinf")).should("have.text", "-4"); - }); - - cy.window().then(async (win) => { - // now move points so that maximum of quadratic interpolating between first two points - // is past maximum of domain - // check for bug where this stopped looking for maxima - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 0, y: 0 }, - }); - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point2", - args: { x: 2, y: 1.8 }, - }); - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point3", - args: { x: 5, y: 4 }, - }); - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point5", - args: { x: 8, y: -1 }, - }); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "1"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,4)"); - }); - cy.get(cesc("#\\/numMinima")).should("have.text", "0"); - cy.get(cesc("#\\/numExtrema")).should("have.text", "1"); - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,4)"); - }); - cy.get(cesc2("#/globalmax")).should("have.text", "4"); - cy.get(cesc2("#/globalsup")).should("have.text", "4"); - cy.get(cesc2("#/globalmin")).should("have.text", "NaN"); - cy.get(cesc2("#/globalinf")).should("have.text", "-2.33"); - }); - - cy.window().then(async (win) => { - // now move points so that the maximum of the cubic interpolating between - // the first two points is past maximum of the domain - // check for bug where this stopped looking for maximum - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 0, y: 0.35 }, - }); - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point2", - args: { x: 1.8, y: 1.36 }, - }); - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point5", - args: { x: 1, y: 0.866 }, - }); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "1"); - cy.get(cesc("#\\/_math1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,4)"); - }); - cy.get(cesc("#\\/numMinima")).should("have.text", "0"); - cy.get(cesc("#\\/numExtrema")).should("have.text", "1"); - cy.get(cesc("#\\/_math3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,4)"); - }); - cy.get(cesc2("#/globalmax")).should("have.text", "4"); - cy.get(cesc2("#/globalsup")).should("have.text", "4"); - cy.get(cesc2("#/globalmin")).should("have.text", "NaN"); - cy.get(cesc2("#/globalinf")).should("have.text", "-12"); - }); - }); - - it("calculated extrema from gaussians", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (0,1) - (3,1) - $_point1.y exp(-(x-$_point1.x)^2)+$_point2.y exp(-(x-$_point2.x)^2) - $_function1.extrema - - -

Number of maxima:

-

Maximum locations: , -

-

Maximum values: , -

-

Number of minima:

-

Minimum locations: , -

-

Minimum values: , -

-

Number of extrema:

-

Extremum locations: , - , -

-

Extremum values: , - , -

-

Global maximum:

-

Global minimum:

- `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "2"); - cy.get(cesc("#\\/maximumlocation1")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(0, 0.01); - }); - cy.get(cesc("#\\/maximumlocation2")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(3, 0.01); - }); - cy.get(cesc("#\\/maximumvalue1")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(1, 0.01); - }); - cy.get(cesc("#\\/maximumvalue2")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(1, 0.01); - }); - - cy.get(cesc("#\\/numMinima")).should("have.text", "1"); - cy.get(cesc("#\\/minimumlocation1")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(1.5, 0.01); - }); - cy.get(cesc("#\\/minimumvalue1")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(0.21, 0.01); - }); - - cy.get(cesc("#\\/numExtrema")).should("have.text", "3"); - cy.get(cesc("#\\/extremumlocation1")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(0, 0.01); - }); - cy.get(cesc("#\\/extremumlocation2")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(1.5, 0.01); - }); - cy.get(cesc("#\\/extremumlocation3")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(3, 0.01); - }); - cy.get(cesc("#\\/extremumvalue1")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(1, 0.01); - }); - cy.get(cesc("#\\/extremumvalue2")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(0.21, 0.01); - }); - cy.get(cesc("#\\/extremumvalue3")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(1, 0.01); - }); - cy.get(cesc2("#/globalmax")).should("have.text", "1"); - cy.get(cesc2("#/globalmin")).should("have.text", "0"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point2", - args: { x: 3, y: -1 }, - }); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "1"); - cy.get(cesc("#\\/maximumlocation1")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(0, 0.01); - }); - cy.get(cesc("#\\/maximumlocation2")).should("not.exist"); - cy.get(cesc("#\\/maximumvalue1")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(1, 0.01); - }); - cy.get(cesc("#\\/maximumvalue2")).should("not.exist"); - - cy.get(cesc("#\\/numMinima")).should("have.text", "1"); - cy.get(cesc("#\\/minimumlocation1")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(3, 0.01); - }); - cy.get(cesc("#\\/minimumvalue1")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(-1, 0.01); - }); - - cy.get(cesc("#\\/numExtrema")).should("have.text", "2"); - cy.get(cesc("#\\/extremumlocation1")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(0, 0.01); - }); - cy.get(cesc("#\\/extremumlocation2")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(3, 0.01); - }); - cy.get(cesc("#\\/extremumlocation3")).should("not.exist"); - cy.get(cesc("#\\/extremumvalue1")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(1, 0.01); - }); - cy.get(cesc("#\\/extremumvalue2")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(-1, 0.01); - }); - cy.get(cesc("#\\/extremumvalue3")).should("not.exist"); - cy.get(cesc2("#/globalmax")).should("have.text", "1"); - cy.get(cesc2("#/globalmin")).should("have.text", "-1"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 0, y: -1 }, - }); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "1"); - cy.get(cesc("#\\/maximumlocation1")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(1.5, 0.01); - }); - cy.get(cesc("#\\/maximumlocation2")).should("not.exist"); - cy.get(cesc("#\\/maximumvalue1")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(-0.21, 0.01); - }); - cy.get(cesc("#\\/maximumvalue2")).should("not.exist"); - - cy.get(cesc("#\\/numMinima")).should("have.text", "2"); - cy.get(cesc("#\\/minimumlocation1")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(0, 0.01); - }); - cy.get(cesc("#\\/minimumlocation2")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(3, 0.01); - }); - cy.get(cesc("#\\/minimumvalue1")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(-1, 0.01); - }); - cy.get(cesc("#\\/minimumvalue2")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(-1, 0.01); - }); - - cy.get(cesc("#\\/numExtrema")).should("have.text", "3"); - cy.get(cesc("#\\/extremumlocation1")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(0, 0.01); - }); - cy.get(cesc("#\\/extremumlocation2")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(1.5, 0.01); - }); - cy.get(cesc("#\\/extremumlocation3")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(3, 0.01); - }); - cy.get(cesc("#\\/extremumvalue1")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(-1, 0.01); - }); - cy.get(cesc("#\\/extremumvalue2")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(-0.21, 0.01); - }); - cy.get(cesc("#\\/extremumvalue3")) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo(-1, 0.01); - }); - cy.get(cesc2("#/globalmax")).should("have.text", "0"); - cy.get(cesc2("#/globalmin")).should("have.text", "-1"); - }); - }); - - it("calculated extrema from sinusoid", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - Period: - - sin(2*pi*x/$_mathinput1) - $_function1.extrema - -

$_function1.maximumLocations

-

$_function1.maximumValues

-

$_function1.minimumLocations

-

$_function1.minimumValues

-

$_function1.extremumLocations

-

$_function1.extremumValues

-

$_mathinput1.value{assignNames="m1"}

- `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let f = stateVariables["/_function1"]; - - expect(f.stateValues.numMaxima).eq(0); - expect(f.stateValues.numMinima).eq(0); - expect(f.stateValues.numExtrema).eq(0); - - expect(f.stateValues.globalMaximum).eqls([]); - expect(f.stateValues.globalSupremum).eqls([]); - expect(f.stateValues.globalMinimum).eqls([]); - expect(f.stateValues.globalInfimum).eqls([]); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type("10{enter}", { - force: true, - }); - cy.get(cesc("#\\/m1")).should("contain.text", "10"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let period = 10; - - let f = stateVariables["/_function1"]; - - expect(f.stateValues.numMaxima).eq(200 / period); - - let maximumLocations = f.stateValues.maximumLocations; - for (let m of maximumLocations) { - expect(((m % period) + period) % period).closeTo( - period / 4, - 0.0001, - ); - } - - let maximumValues = f.stateValues.maximumValues; - for (let m of maximumValues) { - expect(m).closeTo(1, 0.0001); - } - - expect(f.stateValues.numMinima).eq(200 / period); - - let minimumLocations = f.stateValues.minimumLocations; - for (let m of minimumLocations) { - expect(((m % period) + period) % period).closeTo( - (3 * period) / 4, - 0.0001, - ); - } - - let minimumValues = f.stateValues.minimumValues; - for (let m of minimumValues) { - expect(m).closeTo(-1, 0.0001); - } - - expect(f.stateValues.numExtrema).eq(400 / period); - - let extremumLocations = f.stateValues.minimumLocations; - for (let m of extremumLocations) { - expect( - ((m % (period / 2)) + period / 2) % (period / 2), - ).closeTo(period / 4, 0.0001); - } - - let extremumValues = f.stateValues.minimumValues; - for (let m of extremumValues) { - expect(Math.abs(m)).closeTo(1, 0.0001); - } - - expect(f.stateValues.globalMaximum[1]).eq(1); - expect(f.stateValues.globalSupremum[1]).eq(1); - expect(f.stateValues.globalMinimum[1]).eq(-1); - expect(f.stateValues.globalInfimum[1]).eq(-1); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{end}{backspace}{backspace}5{enter}", - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let period = 5; - - let f = stateVariables["/_function1"]; - - expect(f.stateValues.numMaxima).eq(200 / period); - - let maximumLocations = f.stateValues.maximumLocations; - for (let m of maximumLocations) { - expect(((m % period) + period) % period).closeTo( - period / 4, - 0.0001, - ); - } - - let maximumValues = f.stateValues.maximumValues; - for (let m of maximumValues) { - expect(m).closeTo(1, 0.0001); - } - - expect(f.stateValues.numMinima).eq(200 / period); - - let minimumLocations = f.stateValues.minimumLocations; - for (let m of minimumLocations) { - expect(((m % period) + period) % period).closeTo( - (3 * period) / 4, - 0.0001, - ); - } - - let minimumValues = f.stateValues.minimumValues; - for (let m of minimumValues) { - expect(m).closeTo(-1, 0.0001); - } - - expect(f.stateValues.numExtrema).eq(400 / period); - - let extremumLocations = f.stateValues.minimumLocations; - for (let m of extremumLocations) { - expect( - ((m % (period / 2)) + period / 2) % (period / 2), - ).closeTo(period / 4, 0.0001); - } - - let extremumValues = f.stateValues.minimumValues; - for (let m of extremumValues) { - expect(Math.abs(m)).closeTo(1, 0.0001); - } - - expect(f.stateValues.globalMaximum[1]).closeTo(1, 1e-10); - expect(f.stateValues.globalSupremum[1]).closeTo(1, 1e-10); - expect(f.stateValues.globalMinimum[1]).closeTo(-1, 1e-10); - expect(f.stateValues.globalInfimum[1]).closeTo(-1, 1e-10); - }); - }); - - it("calculated extrema from sinusoid, restrict domain", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Period:

-

xmin = - xmax =

- - sin(2*pi*x/$_mathinput1) - $_function1.extrema - -

$_function1.maximumLocations

-

$_function1.maximumValues

-

$_function1.minimumLocations

-

$_function1.minimumValues

-

$_function1.extremumLocations

-

$_function1.extremumValues

-

$_mathinput1.value{assignNames="m1"}

-

$xmax.value{assignNames="xmax2"}

- - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let f = stateVariables["/_function1"]; - - expect(f.stateValues.numMaxima).eq(0); - expect(f.stateValues.numMinima).eq(0); - expect(f.stateValues.numExtrema).eq(0); - expect(f.stateValues.globalMaximum).eqls([]); - expect(f.stateValues.globalSupremum).eqls([]); - expect(f.stateValues.globalMinimum).eqls([]); - expect(f.stateValues.globalInfimum).eqls([]); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type("10{enter}", { - force: true, - }); - cy.get(cesc("#\\/m1")).should("contain.text", "10"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let period = 10; - - let f = stateVariables["/_function1"]; - - expect(f.stateValues.numMaxima).eq(20 / period); - - let maximumLocations = f.stateValues.maximumLocations; - for (let m of maximumLocations) { - expect(((m % period) + period) % period).closeTo( - period / 4, - 0.0001, - ); - } - - let maximumValues = f.stateValues.maximumValues; - for (let m of maximumValues) { - expect(m).closeTo(1, 0.0001); - } - - expect(f.stateValues.numMinima).eq(20 / period); - - let minimumLocations = f.stateValues.minimumLocations; - for (let m of minimumLocations) { - expect(((m % period) + period) % period).closeTo( - (3 * period) / 4, - 0.0001, - ); - } - - let minimumValues = f.stateValues.minimumValues; - for (let m of minimumValues) { - expect(m).closeTo(-1, 0.0001); - } - - expect(f.stateValues.numExtrema).eq(40 / period); - - let extremumLocations = f.stateValues.minimumLocations; - for (let m of extremumLocations) { - expect( - ((m % (period / 2)) + period / 2) % (period / 2), - ).closeTo(period / 4, 0.0001); - } - - let extremumValues = f.stateValues.minimumValues; - for (let m of extremumValues) { - expect(Math.abs(m)).closeTo(1, 0.0001); - } - - expect(f.stateValues.globalMaximum[1]).eq(1); - expect(f.stateValues.globalSupremum[1]).eq(1); - expect(f.stateValues.globalMinimum[1]).eq(-1); - expect(f.stateValues.globalInfimum[1]).eq(-1); - }); - - cy.get(cesc("#\\/xmin") + " textarea").type( - "{end}{backspace}{backspace}5{enter}", - { force: true }, - ); - cy.get(cesc("#\\/xmax") + " textarea").type( - "{end}{backspace}{backspace}25{enter}", - { force: true }, - ); - cy.get(cesc("#\\/xmax2")).should("contain.text", "25"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let period = 10; - - let f = stateVariables["/_function1"]; - - expect(f.stateValues.numMaxima).eq(30 / period); - - let maximumLocations = f.stateValues.maximumLocations; - for (let m of maximumLocations) { - expect(((m % period) + period) % period).closeTo( - period / 4, - 0.0001, - ); - } - - let maximumValues = f.stateValues.maximumValues; - for (let m of maximumValues) { - expect(m).closeTo(1, 0.0001); - } - - expect(f.stateValues.numMinima).eq(30 / period); - - let minimumLocations = f.stateValues.minimumLocations; - for (let m of minimumLocations) { - expect(((m % period) + period) % period).closeTo( - (3 * period) / 4, - 0.0001, - ); - } - - let minimumValues = f.stateValues.minimumValues; - for (let m of minimumValues) { - expect(m).closeTo(-1, 0.0001); - } - - expect(f.stateValues.numExtrema).eq(60 / period); - - let extremumLocations = f.stateValues.minimumLocations; - for (let m of extremumLocations) { - expect( - ((m % (period / 2)) + period / 2) % (period / 2), - ).closeTo(period / 4, 0.0001); - } - - let extremumValues = f.stateValues.minimumValues; - for (let m of extremumValues) { - expect(Math.abs(m)).closeTo(1, 0.0001); - } - - expect(f.stateValues.globalMaximum[1]).eq(1); - expect(f.stateValues.globalSupremum[1]).eq(1); - expect(f.stateValues.globalMinimum[1]).eq(-1); - expect(f.stateValues.globalInfimum[1]).eq(-1); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{end}{backspace}{backspace}5{enter}", - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let period = 5; - - let f = stateVariables["/_function1"]; - - expect(f.stateValues.numMaxima).eq(30 / period); - - let maximumLocations = f.stateValues.maximumLocations; - for (let m of maximumLocations) { - expect(((m % period) + period) % period).closeTo( - period / 4, - 0.0001, - ); - } - - let maximumValues = f.stateValues.maximumValues; - for (let m of maximumValues) { - expect(m).closeTo(1, 0.0001); - } - - expect(f.stateValues.numMinima).eq(30 / period); - - let minimumLocations = f.stateValues.minimumLocations; - for (let m of minimumLocations) { - expect(((m % period) + period) % period).closeTo( - (3 * period) / 4, - 0.0001, - ); - } - - let minimumValues = f.stateValues.minimumValues; - for (let m of minimumValues) { - expect(m).closeTo(-1, 0.0001); - } - - expect(f.stateValues.numExtrema).eq(60 / period); - - let extremumLocations = f.stateValues.minimumLocations; - for (let m of extremumLocations) { - expect( - ((m % (period / 2)) + period / 2) % (period / 2), - ).closeTo(period / 4, 0.0001); - } - - let extremumValues = f.stateValues.minimumValues; - for (let m of extremumValues) { - expect(Math.abs(m)).closeTo(1, 0.0001); - } - - expect(f.stateValues.globalMaximum[1]).eq(1); - expect(f.stateValues.globalSupremum[1]).eq(1); - expect(f.stateValues.globalMinimum[1]).eq(-1); - expect(f.stateValues.globalInfimum[1]).eq(-1); - }); - - cy.get(cesc("#\\/xmin") + " textarea").type( - "{end}{backspace}1{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/xmax") + " textarea").type( - "{end}{backspace}{backspace}9{enter}", - { force: true }, - ); - cy.get(cesc("#\\/xmax2")).should("contain.text", "9"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let period = 5; - - let f = stateVariables["/_function1"]; - - expect(f.stateValues.numMaxima).eq(10 / period); - - let maximumLocations = f.stateValues.maximumLocations; - for (let m of maximumLocations) { - expect(((m % period) + period) % period).closeTo( - period / 4, - 0.0001, - ); - } - - let maximumValues = f.stateValues.maximumValues; - for (let m of maximumValues) { - expect(m).closeTo(1, 0.0001); - } - - expect(f.stateValues.numMinima).eq(10 / period); - - let minimumLocations = f.stateValues.minimumLocations; - for (let m of minimumLocations) { - expect(((m % period) + period) % period).closeTo( - (3 * period) / 4, - 0.0001, - ); - } - - let minimumValues = f.stateValues.minimumValues; - for (let m of minimumValues) { - expect(m).closeTo(-1, 0.0001); - } - - expect(f.stateValues.numExtrema).eq(20 / period); - - let extremumLocations = f.stateValues.minimumLocations; - for (let m of extremumLocations) { - expect( - ((m % (period / 2)) + period / 2) % (period / 2), - ).closeTo(period / 4, 0.0001); - } - - let extremumValues = f.stateValues.minimumValues; - for (let m of extremumValues) { - expect(Math.abs(m)).closeTo(1, 0.0001); - } - - expect(f.stateValues.globalMaximum[1]).eq(1); - expect(f.stateValues.globalSupremum[1]).eq(1); - expect(f.stateValues.globalMinimum[1]).eq(-1); - expect(f.stateValues.globalInfimum[1]).eq(-1); - }); - }); - - it("no extrema with horizontal asymptote", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - 1/(1+exp(-10*x)) - - $_function1.minima - $_function1.maxima - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let f = stateVariables["/_function1"]; - - expect(f.stateValues.numMaxima).eq(0); - expect(f.stateValues.numMinima).eq(0); - expect(f.stateValues.numExtrema).eq(0); - expect(f.stateValues.globalMaximum[1]).eq(1); - expect(f.stateValues.globalSupremum[1]).eq(1); - expect(f.stateValues.globalMinimum[1]).eq(0); - expect(f.stateValues.globalInfimum[1]).eq(0); - }); - }); - - it("extrema of rational function", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - (x+8)(x-8)/((x-2)(x+4)(x-5)^2) - - $_function1.extrema - -

$_function1.maximumLocations

-

$_function1.maximumValues

-

$_function1.minimumLocations

-

$_function1.minimumValues

-

$_function1.extremumLocations

-

$_function1.extremumValues

-

$_function1.globalMaximum, $_function1.globalSupremum, $_function1.globalMinimum, $_function1.globalInfimum

- - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let f = stateVariables["/_function1"]; - - // values of extrema computed in Sage - let minimumLocations = [-2.29152990292159]; - let minimumValues = [0.150710261517204]; - let maximumLocations = [ - -11.6660173492088, 3.18454272065031, 9.77300453148004, - ]; - let maximumValues = [ - 0.00247762462709702, -1.9201441781587, 0.012920204644976, - ]; - - expect(f.stateValues.numMaxima).eq(3); - expect(f.stateValues.numMinima).eq(1); - expect(f.stateValues.numExtrema).eq(4); - - // Note: since just one value, the arrayEntries minimumValues and minimumLocations - // are not arrays. - expect(f.stateValues.minimumValues).closeTo( - minimumValues[0], - 0.000001, - ); - expect(f.stateValues.minimumLocations).closeTo( - minimumLocations[0], - 0.000001, - ); - for (let i in maximumLocations) { - expect(f.stateValues.maximumValues[i]).closeTo( - maximumValues[i], - 0.000001, - ); - expect(f.stateValues.maximumLocations[i]).closeTo( - maximumLocations[i], - 0.000001, - ); - } - expect(f.stateValues.globalMaximum[1]).greaterThan(1e5); - expect(f.stateValues.globalSupremum).eqls( - f.stateValues.globalMaximum, - ); - expect(f.stateValues.globalMinimum[1]).lessThan(-1e5); - expect(f.stateValues.globalInfimum).eqls( - f.stateValues.globalMinimum, - ); - }); - }); - - it("intervals of extrema are not counted", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - $f1.extrema - - $f2.extrema - - $f3.extrema - - $f4.extrema - - $f5.extrema - - $f6.extrema - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let f1 = stateVariables["/f1"]; - let f2 = stateVariables["/f2"]; - let f3 = stateVariables["/f3"]; - let f4 = stateVariables["/f4"]; - let f4fun = createFunctionFromDefinition( - f4.stateValues.fDefinitions[0], - ); - let f5 = stateVariables["/f5"]; - let f6 = stateVariables["/f6"]; - - expect(f1.stateValues.numMaxima).eq(0); - expect(f1.stateValues.numMinima).eq(0); - expect(f1.stateValues.numExtrema).eq(0); - expect(f1.stateValues.globalMinimum).eqls([]); - expect(f1.stateValues.globalInfimum).eqls([Infinity, -Infinity]); - expect(f1.stateValues.globalMaximum).eqls([]); - expect(f1.stateValues.globalSupremum).eqls([-Infinity, Infinity]); - expect(f2.stateValues.numMaxima).eq(0); - expect(f2.stateValues.numMinima).eq(0); - expect(f2.stateValues.numExtrema).eq(0); - expect(f2.stateValues.globalMinimum).eqls([-8, 2]); - expect(f2.stateValues.globalInfimum).eqls([-8, 2]); - expect(f2.stateValues.globalMaximum).eqls([-2, 5]); - expect(f2.stateValues.globalSupremum).eqls([-2, 5]); - expect(f3.stateValues.numMaxima).eq(0); - expect(f3.stateValues.numMinima).eq(0); - expect(f3.stateValues.numExtrema).eq(0); - expect(f3.stateValues.globalMinimum).eqls([-7, 2]); - expect(f3.stateValues.globalInfimum).eqls([-7, 2]); - expect(f3.stateValues.globalMaximum).eqls([-2, 5]); - expect(f3.stateValues.globalSupremum).eqls([-2, 5]); - expect(f4.stateValues.numMaxima).eq(0); - expect(f4.stateValues.numMinima).eq(0); - expect(f4.stateValues.numExtrema).eq(0); - expect(f4.stateValues.globalMinimum).eqls([]); - expect(f4.stateValues.globalInfimum).eqls([14, f4fun(14, true)]); - expect(f4.stateValues.globalMaximum).eqls([]); - expect(f4.stateValues.globalSupremum).eqls([-9, f4fun(-9, true)]); - expect(f5.stateValues.numMaxima).eq(0); - expect(f5.stateValues.numMinima).eq(0); - expect(f5.stateValues.numExtrema).eq(0); - expect(f5.stateValues.globalMinimum).eqls([6, 1]); - expect(f5.stateValues.globalInfimum).eqls([6, 1]); - expect(f5.stateValues.globalMaximum).eqls([-2, 5]); - expect(f5.stateValues.globalSupremum).eqls([-2, 5]); - expect(f6.stateValues.numMaxima).eq(0); - expect(f6.stateValues.numMinima).eq(0); - expect(f6.stateValues.numExtrema).eq(0); - expect(f6.stateValues.globalMinimum).eqls([-8, 2]); - expect(f6.stateValues.globalInfimum).eqls([-8, 2]); - expect(f6.stateValues.globalMaximum).eqls([6, 7]); - expect(f6.stateValues.globalSupremum).eqls([6, 7]); - }); - }); - - it("extrema of function with restricted domain, not explicit", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - log(x^2-1)*sqrt((x-5)^2-1) - - $_function1.extrema - - -

$_function1.maximumLocations

-

$_function1.maximumValues

-

$_function1.minimumLocations

-

$_function1.minimumValues

-

$_function1.extremumLocations

-

$_function1.extremumValues

- - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let f = stateVariables["/_function1"]; - let ffun = createFunctionFromDefinition( - f.stateValues.fDefinitions[0], - ); - - expect(f.stateValues.numMaxima).eq(1); - expect(f.stateValues.numMinima).eq(0); - expect(f.stateValues.numExtrema).eq(1); - - expect(f.stateValues.maximumLocations).closeTo(2.614, 0.001); - expect(f.stateValues.maximumValues).closeTo(3.82, 0.001); - - expect(f.stateValues.globalMaximum).eqls([]); - expect(f.stateValues.globalSupremum).eqls([-100, ffun(-100)]); - expect(f.stateValues.globalMinimum[0]).closeTo(-1, 1e-5); - expect(f.stateValues.globalMinimum[1]).eq( - ffun(f.stateValues.globalMinimum[0]), - ); - expect(f.stateValues.globalInfimum).eqls( - f.stateValues.globalMinimum, - ); - }); - }); - - it("extrema in flat regions of functions", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - 2-(x-1.0131)^10 - 3+(x+pi)^20 - -8+3/(1+exp(-100sin(3x))) - - $f1.extrema - $f2.extrema - $f3.extrema - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let f1 = stateVariables["/f1"]; - let f2 = stateVariables["/f2"]; - let f3 = stateVariables["/f3"]; - let f1fun = createFunctionFromDefinition( - f1.stateValues.fDefinitions[0], - ); - let f2fun = createFunctionFromDefinition( - f2.stateValues.fDefinitions[0], - ); - expect(f1.stateValues.numMaxima).eq(1); - expect(f1.stateValues.numMinima).eq(0); - expect(f1.stateValues.numExtrema).eq(1); - expect(f1.stateValues.maxima[0][0]).closeTo(1.0131, 1e-6); - expect(f1.stateValues.maxima[0][1]).eq(2); - expect(f1.stateValues.extrema[0][0]).closeTo(1.0131, 1e-6); - expect(f1.stateValues.extrema[0][1]).eq(2); - expect(f1.stateValues.globalMaximum).eqls(f1.stateValues.maxima[0]); - expect(f1.stateValues.globalSupremum).eqls( - f1.stateValues.maxima[0], - ); - expect(f1.stateValues.globalMinimum).eqls([]); - expect(f1.stateValues.globalInfimum).eqls([-100, f1fun(-100)]); - - expect(f2.stateValues.numMaxima).eq(0); - expect(f2.stateValues.numMinima).eq(1); - expect(f2.stateValues.numExtrema).eq(1); - expect(f2.stateValues.minima[0][0]).closeTo(-Math.PI, 1e-6); - expect(f2.stateValues.minima[0][1]).eq(3); - expect(f2.stateValues.extrema[0][0]).closeTo(-Math.PI, 1e-6); - expect(f2.stateValues.extrema[0][1]).eq(3); - expect(f2.stateValues.globalMinimum).eqls(f2.stateValues.minima[0]); - expect(f2.stateValues.globalInfimum).eqls(f2.stateValues.minima[0]); - expect(f2.stateValues.globalMaximum).eqls([]); - expect(f2.stateValues.globalSupremum).eqls([100, f2fun(100)]); - - expect(f3.stateValues.numMaxima).eq(2); - expect(f3.stateValues.numMinima).eq(2); - expect(f3.stateValues.numExtrema).eq(4); - expect(f3.stateValues.minima[0][0]).closeTo( - (3 * Math.PI) / 6, - 1e-6, - ); - expect(f3.stateValues.minima[0][1]).eq(-8); - expect(f3.stateValues.minima[1][0]).closeTo( - (7 * Math.PI) / 6, - 1e-6, - ); - expect(f3.stateValues.minima[1][1]).eq(-8); - expect(f3.stateValues.maxima[0][0]).closeTo( - (5 * Math.PI) / 6, - 1e-6, - ); - expect(f3.stateValues.maxima[0][1]).eq(-5); - expect(f3.stateValues.maxima[1][0]).closeTo( - (9 * Math.PI) / 6, - 1e-6, - ); - expect(f3.stateValues.maxima[1][1]).eq(-5); - expect(f3.stateValues.extrema[0][0]).closeTo( - (3 * Math.PI) / 6, - 1e-6, - ); - expect(f3.stateValues.extrema[0][1]).eq(-8); - expect(f3.stateValues.extrema[1][0]).closeTo( - (5 * Math.PI) / 6, - 1e-6, - ); - expect(f3.stateValues.extrema[1][1]).eq(-5); - expect(f3.stateValues.extrema[2][0]).closeTo( - (7 * Math.PI) / 6, - 1e-6, - ); - expect(f3.stateValues.extrema[2][1]).eq(-8); - expect(f3.stateValues.extrema[3][0]).closeTo( - (9 * Math.PI) / 6, - 1e-6, - ); - expect(f3.stateValues.extrema[3][1]).eq(-5); - expect(f3.stateValues.globalMinimum).eqls(f3.stateValues.minima[0]); - expect(f3.stateValues.globalInfimum).eqls(f3.stateValues.minima[0]); - expect(f3.stateValues.globalMaximum).eqls(f3.stateValues.maxima[0]); - expect(f3.stateValues.globalSupremum).eqls( - f3.stateValues.maxima[0], - ); - }); - }); - - it("global extrema, in flat regions too flat for local extrema", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - 2-(x-1.0131)^100 - 3+(x+pi)^200 - -8+3/(1+exp(-1000sin(3x))) - - $f1.extrema - $f2.extrema - $f3.extrema - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let f1 = stateVariables["/f1"]; - let f2 = stateVariables["/f2"]; - let f3 = stateVariables["/f3"]; - let f1fun = createFunctionFromDefinition( - f1.stateValues.fDefinitions[0], - ); - expect(f1.stateValues.numMaxima).eq(0); - expect(f1.stateValues.numMinima).eq(0); - expect(f1.stateValues.numExtrema).eq(0); - expect(f1.stateValues.globalMaximum[0]).within(0.0131, 2.0131); - expect(f1.stateValues.globalMaximum[1]).eqls(2); - expect(f1.stateValues.globalSupremum).eqls( - f1.stateValues.globalMaximum, - ); - expect(f1.stateValues.globalMinimum).eqls([]); - expect(f1.stateValues.globalInfimum).eqls([-100, f1fun(-100)]); - - expect(f2.stateValues.numMaxima).eq(0); - expect(f2.stateValues.numMinima).eq(0); - expect(f2.stateValues.numExtrema).eq(0); - expect(f2.stateValues.globalMinimum[0]).within( - -Math.PI - 1, - -Math.PI + 1, - ); - expect(f2.stateValues.globalMinimum[1]).eqls(3); - expect(f2.stateValues.globalInfimum).eqls( - f2.stateValues.globalMinimum, - ); - expect(f2.stateValues.globalMaximum).eqls([]); - expect(f2.stateValues.globalSupremum[1]).eq(Infinity); - - expect(f3.stateValues.numMaxima).eq(0); - expect(f3.stateValues.numMinima).eq(0); - expect(f3.stateValues.numExtrema).eq(0); - expect(f3.stateValues.globalMinimum[0]).within( - Math.PI / 3, - (2 * Math.PI) / 3, - ); - expect(f3.stateValues.globalMinimum[1]).eqls(-8); - expect(f3.stateValues.globalInfimum).eqls( - f3.stateValues.globalMinimum, - ); - expect(f3.stateValues.globalMaximum[0]).within(1, Math.PI / 3); - expect(f3.stateValues.globalMaximum[1]).eqls(-5); - expect(f3.stateValues.globalSupremum).eqls( - f3.stateValues.globalMaximum, - ); - }); - }); - - it("extrema at domain endpoints, function from formula", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - cos(x) - cos(x)+1 - sin(x)+2 - sin(x)+3 - -

$f1.extrema{assignNames="f1e1 f1e2 f1e3"}

-

$f2.extrema{assignNames="f2e1 f2e2 f2e3 f2e4 f2e5"}

-

$f3.extrema{assignNames="f3e1 f3e2 f3e3 f3e4"}

-

$f4.extrema{assignNames="f4e1 f4e2 f4e3 f4e4"}

- - - cos(x) - sin(x)+2 - sin(x)+3 - -

$f1a.extrema{assignNames="f1ae1 f1ae2 f1ae3"}

-

$f3a.extrema{assignNames="f3ae1 f3ae2 f3ae3 f3ae4"}

-

$f4a.extrema{assignNames="f4ae1 f4ae2 f4ae3 f4ae4"}

- - - cos(x) - cos(x)+1 - cos(x-pi)+4 - cos(x-pi)+5 - - -

$f5.extrema{assignNames="f5e1 f5e2 f5e3"}

-

$f6.extrema{assignNames="f6e1 f6e2 f6e3 f6e4 f6e5"}

-

$f7.extrema{assignNames="f7e1 f7e2 f7e3 f7e4"}

-

$f8.extrema{assignNames="f8e1 f8e2 f8e3 f8e4"}

- - - cos(x) - cos(x)+1 - cos(x-pi)+4 - cos(x-pi)+5 - - -

$f9.extrema{assignNames="f9e1 f9e2 f9e3"}

-

$f10.extrema{assignNames="f10e1 f10e2 f10e3 f10e4 f10e5"}

-

$f11.extrema{assignNames="f11e1 f11e2 f11e3 f11e4"}

-

$f12.extrema{assignNames="f12e1 f12e2 f12e3 f12e4"}

- - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/f1e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq(`(0,1)`); - }); - cy.get(cesc("#\\/f1e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(Math.PI * 10 ** 5) / 10 ** 5, - )},${nInDOM(-1)})`, - ); - }); - cy.get(cesc("#\\/f1e3")).should("not.exist"); - - cy.get(cesc("#\\/f2e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM(Math.round(-Math.PI * 10 ** 5) / 10 ** 5)},0)`, - ); - }); - cy.get(cesc("#\\/f2e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq(`(0,2)`); - }); - cy.get(cesc("#\\/f2e3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM(Math.round(Math.PI * 10 ** 5) / 10 ** 5)},0)`, - ); - }); - cy.get(cesc("#\\/f2e4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(2 * Math.PI * 10 ** 5) / 10 ** 5, - )},2)`, - ); - }); - cy.get(cesc("#\\/f2e5")).should("not.exist"); - - cy.get(cesc("#\\/f3e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(-0.5 * Math.PI * 10 ** 5) / 10 ** 5, - )},1)`, - ); - }); - cy.get(cesc("#\\/f3e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(0.5 * Math.PI * 10 ** 5) / 10 ** 5, - )},3)`, - ); - }); - cy.get(cesc("#\\/f3e3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(1.5 * Math.PI * 10 ** 5) / 10 ** 5, - )},1)`, - ); - }); - cy.get(cesc("#\\/f3e4")).should("not.exist"); - - cy.get(cesc("#\\/f4e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(-1.5 * Math.PI * 10 ** 5) / 10 ** 5, - )},4)`, - ); - }); - cy.get(cesc("#\\/f4e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(-0.5 * Math.PI * 10 ** 5) / 10 ** 5, - )},2)`, - ); - }); - cy.get(cesc("#\\/f4e3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(0.5 * Math.PI * 10 ** 5) / 10 ** 5, - )},4)`, - ); - }); - cy.get(cesc("#\\/f4e4")).should("not.exist"); - - cy.get(cesc("#\\/f1ae1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq(`(0,1)`); - }); - cy.get(cesc("#\\/f1ae2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(Math.PI * 10 ** 5) / 10 ** 5, - )},${nInDOM(-1)})`, - ); - }); - cy.get(cesc("#\\/f1ae3")).should("not.exist"); - - cy.get(cesc("#\\/f3ae1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(-0.5 * Math.PI * 10 ** 5) / 10 ** 5, - )},1)`, - ); - }); - cy.get(cesc("#\\/f3ae2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(0.5 * Math.PI * 10 ** 5) / 10 ** 5, - )},3)`, - ); - }); - cy.get(cesc("#\\/f3ae3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(1.5 * Math.PI * 10 ** 5) / 10 ** 5, - )},1)`, - ); - }); - cy.get(cesc("#\\/f3ae4")).should("not.exist"); - - cy.get(cesc("#\\/f4ae1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(-1.5 * Math.PI * 10 ** 5) / 10 ** 5, - )},4)`, - ); - }); - cy.get(cesc("#\\/f4ae2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(-0.5 * Math.PI * 10 ** 5) / 10 ** 5, - )},2)`, - ); - }); - cy.get(cesc("#\\/f4ae3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(0.5 * Math.PI * 10 ** 5) / 10 ** 5, - )},4)`, - ); - }); - cy.get(cesc("#\\/f4ae4")).should("not.exist"); - - cy.get(cesc("#\\/f5e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(Math.PI * 10 ** 5) / 10 ** 5, - )},${nInDOM(-1)})`, - ); - }); - cy.get(cesc("#\\/f5e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(2 * Math.PI * 10 ** 5) / 10 ** 5, - )},${nInDOM(1)})`, - ); - }); - cy.get(cesc("#\\/f5e3")).should("not.exist"); - - cy.get(cesc("#\\/f6e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq(`(0,2)`); - }); - cy.get(cesc("#\\/f6e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM(Math.round(Math.PI * 10 ** 5) / 10 ** 5)},0)`, - ); - }); - cy.get(cesc("#\\/f6e3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(2 * Math.PI * 10 ** 5) / 10 ** 5, - )},2)`, - ); - }); - cy.get(cesc("#\\/f6e4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(3 * Math.PI * 10 ** 5) / 10 ** 5, - )},0)`, - ); - }); - cy.get(cesc("#\\/f6e5")).should("not.exist"); - - cy.get(cesc("#\\/f7e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM(Math.round(Math.PI * 10 ** 5) / 10 ** 5)},5)`, - ); - }); - cy.get(cesc("#\\/f7e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(2 * Math.PI * 10 ** 5) / 10 ** 5, - )},3)`, - ); - }); - cy.get(cesc("#\\/f7e3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(3 * Math.PI * 10 ** 5) / 10 ** 5, - )},5)`, - ); - }); - cy.get(cesc("#\\/f7e4")).should("not.exist"); - - cy.get(cesc("#\\/f8e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq(`(0,4)`); - }); - cy.get(cesc("#\\/f8e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM(Math.round(Math.PI * 10 ** 5) / 10 ** 5)},6)`, - ); - }); - cy.get(cesc("#\\/f8e3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(2 * Math.PI * 10 ** 5) / 10 ** 5, - )},4)`, - ); - }); - cy.get(cesc("#\\/f8e4")).should("not.exist"); - - cy.get(cesc("#\\/f9e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(-2 * Math.PI * 10 ** 5) / 10 ** 5, - )},${nInDOM(1)})`, - ); - }); - cy.get(cesc("#\\/f9e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(-Math.PI * 10 ** 5) / 10 ** 5, - )},${nInDOM(-1)})`, - ); - }); - cy.get(cesc("#\\/f9e3")).should("not.exist"); - - cy.get(cesc("#\\/f10e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(-3 * Math.PI * 10 ** 5) / 10 ** 5, - )},0)`, - ); - }); - cy.get(cesc("#\\/f10e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(-2 * Math.PI * 10 ** 5) / 10 ** 5, - )},2)`, - ); - }); - cy.get(cesc("#\\/f10e3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM(Math.round(-Math.PI * 10 ** 5) / 10 ** 5)},0)`, - ); - }); - cy.get(cesc("#\\/f10e4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq(`(0,2)`); - }); - cy.get(cesc("#\\/f10e5")).should("not.exist"); - - cy.get(cesc("#\\/f11e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(-2 * Math.PI * 10 ** 5) / 10 ** 5, - )},3)`, - ); - }); - cy.get(cesc("#\\/f11e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM(Math.round(-Math.PI * 10 ** 5) / 10 ** 5)},5)`, - ); - }); - cy.get(cesc("#\\/f11e3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq(`(0,3)`); - }); - cy.get(cesc("#\\/f11e4")).should("not.exist"); - - cy.get(cesc("#\\/f12e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(-3 * Math.PI * 10 ** 5) / 10 ** 5, - )},6)`, - ); - }); - cy.get(cesc("#\\/f12e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(-2 * Math.PI * 10 ** 5) / 10 ** 5, - )},4)`, - ); - }); - cy.get(cesc("#\\/f12e3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM(Math.round(-Math.PI * 10 ** 5) / 10 ** 5)},6)`, - ); - }); - cy.get(cesc("#\\/f12e4")).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let f1 = stateVariables["/f1"]; - let f2 = stateVariables["/f2"]; - let f3 = stateVariables["/f3"]; - let f4 = stateVariables["/f4"]; - expect(f1.stateValues.numMaxima).eq(1); - expect(f1.stateValues.numMinima).eq(1); - expect(f1.stateValues.numExtrema).eq(2); - expect(f1.stateValues.minima[0][0]).closeTo(Math.PI, 1e-6); - expect(f1.stateValues.minima[0][1]).eq(-1); - expect(f1.stateValues.maxima[0][0]).closeTo(0, 1e-6); - expect(f1.stateValues.maxima[0][1]).eq(1); - expect(f1.stateValues.extrema[0][0]).closeTo(0, 1e-6); - expect(f1.stateValues.extrema[0][1]).eq(1); - expect(f1.stateValues.extrema[1][0]).closeTo(Math.PI, 1e-6); - expect(f1.stateValues.extrema[1][1]).eq(-1); - - expect(f2.stateValues.numMaxima).eq(2); - expect(f2.stateValues.numMinima).eq(2); - expect(f2.stateValues.numExtrema).eq(4); - expect(f2.stateValues.minima[0][0]).closeTo(-Math.PI, 1e-6); - expect(f2.stateValues.minima[0][1]).eq(0); - expect(f2.stateValues.minima[1][0]).closeTo(Math.PI, 1e-6); - expect(f2.stateValues.minima[1][1]).eq(0); - expect(f2.stateValues.maxima[0][0]).closeTo(0, 1e-6); - expect(f2.stateValues.maxima[0][1]).eq(2); - expect(f2.stateValues.maxima[1][0]).closeTo(2 * Math.PI, 1e-6); - expect(f2.stateValues.maxima[1][1]).eq(2); - expect(f2.stateValues.extrema[0][0]).closeTo(-Math.PI, 1e-6); - expect(f2.stateValues.extrema[0][1]).eq(0); - expect(f2.stateValues.extrema[1][0]).closeTo(0, 1e-6); - expect(f2.stateValues.extrema[1][1]).eq(2); - expect(f2.stateValues.extrema[2][0]).closeTo(Math.PI, 1e-6); - expect(f2.stateValues.extrema[2][1]).eq(0); - expect(f2.stateValues.extrema[3][0]).closeTo(2 * Math.PI, 1e-6); - expect(f2.stateValues.extrema[3][1]).eq(2); - - expect(f3.stateValues.numMaxima).eq(1); - expect(f3.stateValues.numMinima).eq(2); - expect(f3.stateValues.numExtrema).eq(3); - expect(f3.stateValues.minima[0][0]).closeTo(-0.5 * Math.PI, 1e-6); - expect(f3.stateValues.minima[0][1]).eq(1); - expect(f3.stateValues.minima[1][0]).closeTo(1.5 * Math.PI, 1e-6); - expect(f3.stateValues.minima[1][1]).eq(1); - expect(f3.stateValues.maxima[0][0]).closeTo(0.5 * Math.PI, 1e-6); - expect(f3.stateValues.maxima[0][1]).eq(3); - expect(f3.stateValues.extrema[0][0]).closeTo(-0.5 * Math.PI, 1e-6); - expect(f3.stateValues.extrema[0][1]).eq(1); - expect(f3.stateValues.extrema[1][0]).closeTo(0.5 * Math.PI, 1e-6); - expect(f3.stateValues.extrema[1][1]).eq(3); - expect(f3.stateValues.extrema[2][0]).closeTo(1.5 * Math.PI, 1e-6); - expect(f3.stateValues.extrema[2][1]).eq(1); - - expect(f4.stateValues.numMaxima).eq(2); - expect(f4.stateValues.numMinima).eq(1); - expect(f4.stateValues.numExtrema).eq(3); - expect(f4.stateValues.minima[0][0]).closeTo(-0.5 * Math.PI, 1e-6); - expect(f4.stateValues.minima[0][1]).eq(2); - expect(f4.stateValues.maxima[0][0]).closeTo(-1.5 * Math.PI, 1e-6); - expect(f4.stateValues.maxima[0][1]).eq(4); - expect(f4.stateValues.maxima[1][0]).closeTo(0.5 * Math.PI, 1e-6); - expect(f4.stateValues.maxima[1][1]).eq(4); - expect(f4.stateValues.extrema[0][0]).closeTo(-1.5 * Math.PI, 1e-6); - expect(f4.stateValues.extrema[0][1]).eq(4); - expect(f4.stateValues.extrema[1][0]).closeTo(-0.5 * Math.PI, 1e-6); - expect(f4.stateValues.extrema[1][1]).eq(2); - expect(f4.stateValues.extrema[2][0]).closeTo(0.5 * Math.PI, 1e-6); - expect(f4.stateValues.extrema[2][1]).eq(4); - - let f1a = stateVariables["/f1a"]; - let f2a = stateVariables["/f2a"]; - let f3a = stateVariables["/f3a"]; - let f4a = stateVariables["/f4a"]; - expect(f1a.stateValues.numMaxima).eq(1); - expect(f1a.stateValues.numMinima).eq(1); - expect(f1a.stateValues.numExtrema).eq(2); - expect(f1a.stateValues.minima[0][0]).closeTo(Math.PI, 1e-6); - expect(f1a.stateValues.minima[0][1]).eq(-1); - expect(f1a.stateValues.maxima[0][0]).closeTo(0, 1e-6); - expect(f1a.stateValues.maxima[0][1]).eq(1); - expect(f1a.stateValues.extrema[0][0]).closeTo(0, 1e-6); - expect(f1a.stateValues.extrema[0][1]).eq(1); - expect(f1a.stateValues.extrema[1][0]).closeTo(Math.PI, 1e-6); - expect(f1a.stateValues.extrema[1][1]).eq(-1); - - expect(f3a.stateValues.numMaxima).eq(1); - expect(f3a.stateValues.numMinima).eq(2); - expect(f3a.stateValues.numExtrema).eq(3); - expect(f3a.stateValues.minima[0][0]).closeTo(-0.5 * Math.PI, 1e-6); - expect(f3a.stateValues.minima[0][1]).eq(1); - expect(f3a.stateValues.minima[1][0]).closeTo(1.5 * Math.PI, 1e-6); - expect(f3a.stateValues.minima[1][1]).eq(1); - expect(f3a.stateValues.maxima[0][0]).closeTo(0.5 * Math.PI, 1e-6); - expect(f3a.stateValues.maxima[0][1]).eq(3); - expect(f3a.stateValues.extrema[0][0]).closeTo(-0.5 * Math.PI, 1e-6); - expect(f3a.stateValues.extrema[0][1]).eq(1); - expect(f3a.stateValues.extrema[1][0]).closeTo(0.5 * Math.PI, 1e-6); - expect(f3a.stateValues.extrema[1][1]).eq(3); - expect(f3a.stateValues.extrema[2][0]).closeTo(1.5 * Math.PI, 1e-6); - expect(f3a.stateValues.extrema[2][1]).eq(1); - - expect(f4a.stateValues.numMaxima).eq(2); - expect(f4a.stateValues.numMinima).eq(1); - expect(f4a.stateValues.numExtrema).eq(3); - expect(f4a.stateValues.minima[0][0]).closeTo(-0.5 * Math.PI, 1e-6); - expect(f4a.stateValues.minima[0][1]).eq(2); - expect(f4a.stateValues.maxima[0][0]).closeTo(-1.5 * Math.PI, 1e-6); - expect(f4a.stateValues.maxima[0][1]).eq(4); - expect(f4a.stateValues.maxima[1][0]).closeTo(0.5 * Math.PI, 1e-6); - expect(f4a.stateValues.maxima[1][1]).eq(4); - expect(f4a.stateValues.extrema[0][0]).closeTo(-1.5 * Math.PI, 1e-6); - expect(f4a.stateValues.extrema[0][1]).eq(4); - expect(f4a.stateValues.extrema[1][0]).closeTo(-0.5 * Math.PI, 1e-6); - expect(f4a.stateValues.extrema[1][1]).eq(2); - expect(f4a.stateValues.extrema[2][0]).closeTo(0.5 * Math.PI, 1e-6); - expect(f4a.stateValues.extrema[2][1]).eq(4); - - let f5 = stateVariables["/f5"]; - let f6 = stateVariables["/f6"]; - let f7 = stateVariables["/f7"]; - let f8 = stateVariables["/f8"]; - expect(f5.stateValues.numMaxima).eq(1); - expect(f5.stateValues.numMinima).eq(1); - expect(f5.stateValues.numExtrema).eq(2); - expect(f5.stateValues.minima[0][0]).closeTo(Math.PI, 1e-6); - expect(f5.stateValues.minima[0][1]).eq(-1); - expect(f5.stateValues.maxima[0][0]).closeTo(2 * Math.PI, 1e-6); - expect(f5.stateValues.maxima[0][1]).eq(1); - expect(f5.stateValues.extrema[0][0]).closeTo(Math.PI, 1e-6); - expect(f5.stateValues.extrema[0][1]).eq(-1); - expect(f5.stateValues.extrema[1][0]).closeTo(2 * Math.PI, 1e-6); - expect(f5.stateValues.extrema[1][1]).eq(1); - - expect(f6.stateValues.numMaxima).eq(2); - expect(f6.stateValues.numMinima).eq(2); - expect(f6.stateValues.numExtrema).eq(4); - expect(f6.stateValues.minima[0][0]).closeTo(Math.PI, 1e-6); - expect(f6.stateValues.minima[0][1]).eq(0); - expect(f6.stateValues.minima[1][0]).closeTo(3 * Math.PI, 1e-6); - expect(f6.stateValues.minima[1][1]).eq(0); - expect(f6.stateValues.maxima[0][0]).closeTo(0, 1e-6); - expect(f6.stateValues.maxima[0][1]).eq(2); - expect(f6.stateValues.maxima[1][0]).closeTo(2 * Math.PI, 1e-6); - expect(f6.stateValues.maxima[1][1]).eq(2); - expect(f6.stateValues.extrema[0][0]).closeTo(0, 1e-6); - expect(f6.stateValues.extrema[0][1]).eq(2); - expect(f6.stateValues.extrema[1][0]).closeTo(Math.PI, 1e-6); - expect(f6.stateValues.extrema[1][1]).eq(0); - expect(f6.stateValues.extrema[2][0]).closeTo(2 * Math.PI, 1e-6); - expect(f6.stateValues.extrema[2][1]).eq(2); - expect(f6.stateValues.extrema[3][0]).closeTo(3 * Math.PI, 1e-6); - expect(f6.stateValues.extrema[3][1]).eq(0); - - expect(f7.stateValues.numMaxima).eq(2); - expect(f7.stateValues.numMinima).eq(1); - expect(f7.stateValues.numExtrema).eq(3); - expect(f7.stateValues.minima[0][0]).closeTo(2 * Math.PI, 1e-6); - expect(f7.stateValues.minima[0][1]).eq(3); - expect(f7.stateValues.maxima[0][0]).closeTo(Math.PI, 1e-6); - expect(f7.stateValues.maxima[0][1]).eq(5); - expect(f7.stateValues.maxima[1][0]).closeTo(3 * Math.PI, 1e-6); - expect(f7.stateValues.maxima[1][1]).eq(5); - expect(f7.stateValues.extrema[0][0]).closeTo(Math.PI, 1e-6); - expect(f7.stateValues.extrema[0][1]).eq(5); - expect(f7.stateValues.extrema[1][0]).closeTo(2 * Math.PI, 1e-6); - expect(f7.stateValues.extrema[1][1]).eq(3); - expect(f7.stateValues.extrema[2][0]).closeTo(3 * Math.PI, 1e-6); - expect(f7.stateValues.extrema[2][1]).eq(5); - - expect(f8.stateValues.numMaxima).eq(1); - expect(f8.stateValues.numMinima).eq(2); - expect(f8.stateValues.numExtrema).eq(3); - expect(f8.stateValues.minima[0][0]).closeTo(0, 1e-6); - expect(f8.stateValues.minima[0][1]).eq(4); - expect(f8.stateValues.minima[1][0]).closeTo(2 * Math.PI, 1e-6); - expect(f8.stateValues.minima[1][1]).eq(4); - expect(f8.stateValues.maxima[0][0]).closeTo(Math.PI, 1e-6); - expect(f8.stateValues.maxima[0][1]).eq(6); - expect(f8.stateValues.extrema[0][0]).closeTo(0, 1e-6); - expect(f8.stateValues.extrema[0][1]).eq(4); - expect(f8.stateValues.extrema[1][0]).closeTo(Math.PI, 1e-6); - expect(f8.stateValues.extrema[1][1]).eq(6); - expect(f8.stateValues.extrema[2][0]).closeTo(2 * Math.PI, 1e-6); - expect(f8.stateValues.extrema[2][1]).eq(4); - - let f9 = stateVariables["/f9"]; - let f10 = stateVariables["/f10"]; - let f11 = stateVariables["/f11"]; - let f12 = stateVariables["/f12"]; - expect(f9.stateValues.numMaxima).eq(1); - expect(f9.stateValues.numMinima).eq(1); - expect(f9.stateValues.numExtrema).eq(2); - expect(f9.stateValues.minima[0][0]).closeTo(-Math.PI, 1e-6); - expect(f9.stateValues.minima[0][1]).eq(-1); - expect(f9.stateValues.maxima[0][0]).closeTo(-2 * Math.PI, 1e-6); - expect(f9.stateValues.maxima[0][1]).eq(1); - expect(f9.stateValues.extrema[0][0]).closeTo(-2 * Math.PI, 1e-6); - expect(f9.stateValues.extrema[0][1]).eq(1); - expect(f9.stateValues.extrema[1][0]).closeTo(-Math.PI, 1e-6); - expect(f9.stateValues.extrema[1][1]).eq(-1); - - expect(f10.stateValues.numMaxima).eq(2); - expect(f10.stateValues.numMinima).eq(2); - expect(f10.stateValues.numExtrema).eq(4); - expect(f10.stateValues.minima[0][0]).closeTo(-3 * Math.PI, 1e-6); - expect(f10.stateValues.minima[0][1]).eq(0); - expect(f10.stateValues.minima[1][0]).closeTo(-Math.PI, 1e-6); - expect(f10.stateValues.minima[1][1]).eq(0); - expect(f10.stateValues.maxima[0][0]).closeTo(-2 * Math.PI, 1e-6); - expect(f10.stateValues.maxima[0][1]).eq(2); - expect(f10.stateValues.maxima[1][0]).closeTo(0, 1e-6); - expect(f10.stateValues.maxima[1][1]).eq(2); - expect(f10.stateValues.extrema[0][0]).closeTo(-3 * Math.PI, 1e-6); - expect(f10.stateValues.extrema[0][1]).eq(0); - expect(f10.stateValues.extrema[1][0]).closeTo(-2 * Math.PI, 1e-6); - expect(f10.stateValues.extrema[1][1]).eq(2); - expect(f10.stateValues.extrema[2][0]).closeTo(-Math.PI, 1e-6); - expect(f10.stateValues.extrema[2][1]).eq(0); - expect(f10.stateValues.extrema[3][0]).closeTo(0, 1e-6); - expect(f10.stateValues.extrema[3][1]).eq(2); - - expect(f11.stateValues.numMaxima).eq(1); - expect(f11.stateValues.numMinima).eq(2); - expect(f11.stateValues.numExtrema).eq(3); - expect(f11.stateValues.minima[0][0]).closeTo(-2 * Math.PI, 1e-6); - expect(f11.stateValues.minima[0][1]).eq(3); - expect(f11.stateValues.minima[1][0]).closeTo(0, 1e-6); - expect(f11.stateValues.minima[1][1]).eq(3); - expect(f11.stateValues.maxima[0][0]).closeTo(-Math.PI, 1e-6); - expect(f11.stateValues.maxima[0][1]).eq(5); - expect(f11.stateValues.extrema[0][0]).closeTo(-2 * Math.PI, 1e-6); - expect(f11.stateValues.extrema[0][1]).eq(3); - expect(f11.stateValues.extrema[1][0]).closeTo(-Math.PI, 1e-6); - expect(f11.stateValues.extrema[1][1]).eq(5); - expect(f11.stateValues.extrema[2][0]).closeTo(0, 1e-6); - expect(f11.stateValues.extrema[2][1]).eq(3); - - expect(f12.stateValues.numMaxima).eq(2); - expect(f12.stateValues.numMinima).eq(1); - expect(f12.stateValues.numExtrema).eq(3); - expect(f12.stateValues.minima[0][0]).closeTo(-2 * Math.PI, 1e-6); - expect(f12.stateValues.minima[0][1]).eq(4); - expect(f12.stateValues.maxima[0][0]).closeTo(-3 * Math.PI, 1e-6); - expect(f12.stateValues.maxima[0][1]).eq(6); - expect(f12.stateValues.maxima[1][0]).closeTo(-Math.PI, 1e-6); - expect(f12.stateValues.maxima[1][1]).eq(6); - expect(f12.stateValues.extrema[0][0]).closeTo(-3 * Math.PI, 1e-6); - expect(f12.stateValues.extrema[0][1]).eq(6); - expect(f12.stateValues.extrema[1][0]).closeTo(-2 * Math.PI, 1e-6); - expect(f12.stateValues.extrema[1][1]).eq(4); - expect(f12.stateValues.extrema[2][0]).closeTo(-Math.PI, 1e-6); - expect(f12.stateValues.extrema[2][1]).eq(6); - }); - }); - - it("extrema at domain endpoints, function from formula, link=false", () => { - // Note: checking to see if rounding attributes are properly copied - // for wrapped array state variables when link="false" - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - cos(x) - cos(x)+1 - sin(x)+2 - sin(x)+3 - -

-

-

-

- - - cos(x) - sin(x)+2 - sin(x)+3 - -

-

-

- - - cos(x) - cos(x)+1 - cos(x-pi)+4 - cos(x-pi)+5 - - -

-

-

-

- - - cos(x) - cos(x)+1 - cos(x-pi)+4 - cos(x-pi)+5 - - -

-

-

-

- - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/f1e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq(`(0,1)`); - }); - cy.get(cesc("#\\/f1e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(Math.PI * 10 ** 5) / 10 ** 5, - )},${nInDOM(-1)})`, - ); - }); - cy.get(cesc("#\\/f1e3")).should("not.exist"); - - cy.get(cesc("#\\/f2e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM(Math.round(-Math.PI * 10 ** 5) / 10 ** 5)},0)`, - ); - }); - cy.get(cesc("#\\/f2e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq(`(0,2)`); - }); - cy.get(cesc("#\\/f2e3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM(Math.round(Math.PI * 10 ** 5) / 10 ** 5)},0)`, - ); - }); - cy.get(cesc("#\\/f2e4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(2 * Math.PI * 10 ** 5) / 10 ** 5, - )},2)`, - ); - }); - cy.get(cesc("#\\/f2e5")).should("not.exist"); - - cy.get(cesc("#\\/f3e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(-0.5 * Math.PI * 10 ** 5) / 10 ** 5, - )},1)`, - ); - }); - cy.get(cesc("#\\/f3e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(0.5 * Math.PI * 10 ** 5) / 10 ** 5, - )},3)`, - ); - }); - cy.get(cesc("#\\/f3e3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(1.5 * Math.PI * 10 ** 5) / 10 ** 5, - )},1)`, - ); - }); - cy.get(cesc("#\\/f3e4")).should("not.exist"); - - cy.get(cesc("#\\/f4e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(-1.5 * Math.PI * 10 ** 5) / 10 ** 5, - )},4)`, - ); - }); - cy.get(cesc("#\\/f4e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(-0.5 * Math.PI * 10 ** 5) / 10 ** 5, - )},2)`, - ); - }); - cy.get(cesc("#\\/f4e3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(0.5 * Math.PI * 10 ** 5) / 10 ** 5, - )},4)`, - ); - }); - cy.get(cesc("#\\/f4e4")).should("not.exist"); - - cy.get(cesc("#\\/f1ae1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq(`(0,1)`); - }); - cy.get(cesc("#\\/f1ae2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(Math.PI * 10 ** 5) / 10 ** 5, - )},${nInDOM(-1)})`, - ); - }); - cy.get(cesc("#\\/f1ae3")).should("not.exist"); - - cy.get(cesc("#\\/f3ae1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(-0.5 * Math.PI * 10 ** 5) / 10 ** 5, - )},1)`, - ); - }); - cy.get(cesc("#\\/f3ae2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(0.5 * Math.PI * 10 ** 5) / 10 ** 5, - )},3)`, - ); - }); - cy.get(cesc("#\\/f3ae3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(1.5 * Math.PI * 10 ** 5) / 10 ** 5, - )},1)`, - ); - }); - cy.get(cesc("#\\/f3ae4")).should("not.exist"); - - cy.get(cesc("#\\/f4ae1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(-1.5 * Math.PI * 10 ** 5) / 10 ** 5, - )},4)`, - ); - }); - cy.get(cesc("#\\/f4ae2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(-0.5 * Math.PI * 10 ** 5) / 10 ** 5, - )},2)`, - ); - }); - cy.get(cesc("#\\/f4ae3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(0.5 * Math.PI * 10 ** 5) / 10 ** 5, - )},4)`, - ); - }); - cy.get(cesc("#\\/f4ae4")).should("not.exist"); - - cy.get(cesc("#\\/f5e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(Math.PI * 10 ** 5) / 10 ** 5, - )},${nInDOM(-1)})`, - ); - }); - cy.get(cesc("#\\/f5e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(2 * Math.PI * 10 ** 5) / 10 ** 5, - )},${nInDOM(1)})`, - ); - }); - cy.get(cesc("#\\/f5e3")).should("not.exist"); - - cy.get(cesc("#\\/f6e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq(`(0,2)`); - }); - cy.get(cesc("#\\/f6e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM(Math.round(Math.PI * 10 ** 5) / 10 ** 5)},0)`, - ); - }); - cy.get(cesc("#\\/f6e3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(2 * Math.PI * 10 ** 5) / 10 ** 5, - )},2)`, - ); - }); - cy.get(cesc("#\\/f6e4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(3 * Math.PI * 10 ** 5) / 10 ** 5, - )},0)`, - ); - }); - cy.get(cesc("#\\/f6e5")).should("not.exist"); - - cy.get(cesc("#\\/f7e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM(Math.round(Math.PI * 10 ** 5) / 10 ** 5)},5)`, - ); - }); - cy.get(cesc("#\\/f7e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(2 * Math.PI * 10 ** 5) / 10 ** 5, - )},3)`, - ); - }); - cy.get(cesc("#\\/f7e3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(3 * Math.PI * 10 ** 5) / 10 ** 5, - )},5)`, - ); - }); - cy.get(cesc("#\\/f7e4")).should("not.exist"); - - cy.get(cesc("#\\/f8e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq(`(0,4)`); - }); - cy.get(cesc("#\\/f8e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM(Math.round(Math.PI * 10 ** 5) / 10 ** 5)},6)`, - ); - }); - cy.get(cesc("#\\/f8e3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(2 * Math.PI * 10 ** 5) / 10 ** 5, - )},4)`, - ); - }); - cy.get(cesc("#\\/f8e4")).should("not.exist"); - - cy.get(cesc("#\\/f9e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(-2 * Math.PI * 10 ** 5) / 10 ** 5, - )},${nInDOM(1)})`, - ); - }); - cy.get(cesc("#\\/f9e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(-Math.PI * 10 ** 5) / 10 ** 5, - )},${nInDOM(-1)})`, - ); - }); - cy.get(cesc("#\\/f9e3")).should("not.exist"); - - cy.get(cesc("#\\/f10e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(-3 * Math.PI * 10 ** 5) / 10 ** 5, - )},0)`, - ); - }); - cy.get(cesc("#\\/f10e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(-2 * Math.PI * 10 ** 5) / 10 ** 5, - )},2)`, - ); - }); - cy.get(cesc("#\\/f10e3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM(Math.round(-Math.PI * 10 ** 5) / 10 ** 5)},0)`, - ); - }); - cy.get(cesc("#\\/f10e4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq(`(0,2)`); - }); - cy.get(cesc("#\\/f10e5")).should("not.exist"); - - cy.get(cesc("#\\/f11e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(-2 * Math.PI * 10 ** 5) / 10 ** 5, - )},3)`, - ); - }); - cy.get(cesc("#\\/f11e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM(Math.round(-Math.PI * 10 ** 5) / 10 ** 5)},5)`, - ); - }); - cy.get(cesc("#\\/f11e3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq(`(0,3)`); - }); - cy.get(cesc("#\\/f11e4")).should("not.exist"); - - cy.get(cesc("#\\/f12e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(-3 * Math.PI * 10 ** 5) / 10 ** 5, - )},6)`, - ); - }); - cy.get(cesc("#\\/f12e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(-2 * Math.PI * 10 ** 5) / 10 ** 5, - )},4)`, - ); - }); - cy.get(cesc("#\\/f12e3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM(Math.round(-Math.PI * 10 ** 5) / 10 ** 5)},6)`, - ); - }); - cy.get(cesc("#\\/f12e4")).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let f1 = stateVariables["/f1"]; - let f2 = stateVariables["/f2"]; - let f3 = stateVariables["/f3"]; - let f4 = stateVariables["/f4"]; - expect(f1.stateValues.numMaxima).eq(1); - expect(f1.stateValues.numMinima).eq(1); - expect(f1.stateValues.numExtrema).eq(2); - expect(f1.stateValues.minima[0][0]).closeTo(Math.PI, 1e-6); - expect(f1.stateValues.minima[0][1]).eq(-1); - expect(f1.stateValues.maxima[0][0]).closeTo(0, 1e-6); - expect(f1.stateValues.maxima[0][1]).eq(1); - expect(f1.stateValues.extrema[0][0]).closeTo(0, 1e-6); - expect(f1.stateValues.extrema[0][1]).eq(1); - expect(f1.stateValues.extrema[1][0]).closeTo(Math.PI, 1e-6); - expect(f1.stateValues.extrema[1][1]).eq(-1); - - expect(f2.stateValues.numMaxima).eq(2); - expect(f2.stateValues.numMinima).eq(2); - expect(f2.stateValues.numExtrema).eq(4); - expect(f2.stateValues.minima[0][0]).closeTo(-Math.PI, 1e-6); - expect(f2.stateValues.minima[0][1]).eq(0); - expect(f2.stateValues.minima[1][0]).closeTo(Math.PI, 1e-6); - expect(f2.stateValues.minima[1][1]).eq(0); - expect(f2.stateValues.maxima[0][0]).closeTo(0, 1e-6); - expect(f2.stateValues.maxima[0][1]).eq(2); - expect(f2.stateValues.maxima[1][0]).closeTo(2 * Math.PI, 1e-6); - expect(f2.stateValues.maxima[1][1]).eq(2); - expect(f2.stateValues.extrema[0][0]).closeTo(-Math.PI, 1e-6); - expect(f2.stateValues.extrema[0][1]).eq(0); - expect(f2.stateValues.extrema[1][0]).closeTo(0, 1e-6); - expect(f2.stateValues.extrema[1][1]).eq(2); - expect(f2.stateValues.extrema[2][0]).closeTo(Math.PI, 1e-6); - expect(f2.stateValues.extrema[2][1]).eq(0); - expect(f2.stateValues.extrema[3][0]).closeTo(2 * Math.PI, 1e-6); - expect(f2.stateValues.extrema[3][1]).eq(2); - - expect(f3.stateValues.numMaxima).eq(1); - expect(f3.stateValues.numMinima).eq(2); - expect(f3.stateValues.numExtrema).eq(3); - expect(f3.stateValues.minima[0][0]).closeTo(-0.5 * Math.PI, 1e-6); - expect(f3.stateValues.minima[0][1]).eq(1); - expect(f3.stateValues.minima[1][0]).closeTo(1.5 * Math.PI, 1e-6); - expect(f3.stateValues.minima[1][1]).eq(1); - expect(f3.stateValues.maxima[0][0]).closeTo(0.5 * Math.PI, 1e-6); - expect(f3.stateValues.maxima[0][1]).eq(3); - expect(f3.stateValues.extrema[0][0]).closeTo(-0.5 * Math.PI, 1e-6); - expect(f3.stateValues.extrema[0][1]).eq(1); - expect(f3.stateValues.extrema[1][0]).closeTo(0.5 * Math.PI, 1e-6); - expect(f3.stateValues.extrema[1][1]).eq(3); - expect(f3.stateValues.extrema[2][0]).closeTo(1.5 * Math.PI, 1e-6); - expect(f3.stateValues.extrema[2][1]).eq(1); - - expect(f4.stateValues.numMaxima).eq(2); - expect(f4.stateValues.numMinima).eq(1); - expect(f4.stateValues.numExtrema).eq(3); - expect(f4.stateValues.minima[0][0]).closeTo(-0.5 * Math.PI, 1e-6); - expect(f4.stateValues.minima[0][1]).eq(2); - expect(f4.stateValues.maxima[0][0]).closeTo(-1.5 * Math.PI, 1e-6); - expect(f4.stateValues.maxima[0][1]).eq(4); - expect(f4.stateValues.maxima[1][0]).closeTo(0.5 * Math.PI, 1e-6); - expect(f4.stateValues.maxima[1][1]).eq(4); - expect(f4.stateValues.extrema[0][0]).closeTo(-1.5 * Math.PI, 1e-6); - expect(f4.stateValues.extrema[0][1]).eq(4); - expect(f4.stateValues.extrema[1][0]).closeTo(-0.5 * Math.PI, 1e-6); - expect(f4.stateValues.extrema[1][1]).eq(2); - expect(f4.stateValues.extrema[2][0]).closeTo(0.5 * Math.PI, 1e-6); - expect(f4.stateValues.extrema[2][1]).eq(4); - - let f1a = stateVariables["/f1a"]; - let f2a = stateVariables["/f2a"]; - let f3a = stateVariables["/f3a"]; - let f4a = stateVariables["/f4a"]; - expect(f1a.stateValues.numMaxima).eq(1); - expect(f1a.stateValues.numMinima).eq(1); - expect(f1a.stateValues.numExtrema).eq(2); - expect(f1a.stateValues.minima[0][0]).closeTo(Math.PI, 1e-6); - expect(f1a.stateValues.minima[0][1]).eq(-1); - expect(f1a.stateValues.maxima[0][0]).closeTo(0, 1e-6); - expect(f1a.stateValues.maxima[0][1]).eq(1); - expect(f1a.stateValues.extrema[0][0]).closeTo(0, 1e-6); - expect(f1a.stateValues.extrema[0][1]).eq(1); - expect(f1a.stateValues.extrema[1][0]).closeTo(Math.PI, 1e-6); - expect(f1a.stateValues.extrema[1][1]).eq(-1); - - expect(f3a.stateValues.numMaxima).eq(1); - expect(f3a.stateValues.numMinima).eq(2); - expect(f3a.stateValues.numExtrema).eq(3); - expect(f3a.stateValues.minima[0][0]).closeTo(-0.5 * Math.PI, 1e-6); - expect(f3a.stateValues.minima[0][1]).eq(1); - expect(f3a.stateValues.minima[1][0]).closeTo(1.5 * Math.PI, 1e-6); - expect(f3a.stateValues.minima[1][1]).eq(1); - expect(f3a.stateValues.maxima[0][0]).closeTo(0.5 * Math.PI, 1e-6); - expect(f3a.stateValues.maxima[0][1]).eq(3); - expect(f3a.stateValues.extrema[0][0]).closeTo(-0.5 * Math.PI, 1e-6); - expect(f3a.stateValues.extrema[0][1]).eq(1); - expect(f3a.stateValues.extrema[1][0]).closeTo(0.5 * Math.PI, 1e-6); - expect(f3a.stateValues.extrema[1][1]).eq(3); - expect(f3a.stateValues.extrema[2][0]).closeTo(1.5 * Math.PI, 1e-6); - expect(f3a.stateValues.extrema[2][1]).eq(1); - - expect(f4a.stateValues.numMaxima).eq(2); - expect(f4a.stateValues.numMinima).eq(1); - expect(f4a.stateValues.numExtrema).eq(3); - expect(f4a.stateValues.minima[0][0]).closeTo(-0.5 * Math.PI, 1e-6); - expect(f4a.stateValues.minima[0][1]).eq(2); - expect(f4a.stateValues.maxima[0][0]).closeTo(-1.5 * Math.PI, 1e-6); - expect(f4a.stateValues.maxima[0][1]).eq(4); - expect(f4a.stateValues.maxima[1][0]).closeTo(0.5 * Math.PI, 1e-6); - expect(f4a.stateValues.maxima[1][1]).eq(4); - expect(f4a.stateValues.extrema[0][0]).closeTo(-1.5 * Math.PI, 1e-6); - expect(f4a.stateValues.extrema[0][1]).eq(4); - expect(f4a.stateValues.extrema[1][0]).closeTo(-0.5 * Math.PI, 1e-6); - expect(f4a.stateValues.extrema[1][1]).eq(2); - expect(f4a.stateValues.extrema[2][0]).closeTo(0.5 * Math.PI, 1e-6); - expect(f4a.stateValues.extrema[2][1]).eq(4); - - let f5 = stateVariables["/f5"]; - let f6 = stateVariables["/f6"]; - let f7 = stateVariables["/f7"]; - let f8 = stateVariables["/f8"]; - expect(f5.stateValues.numMaxima).eq(1); - expect(f5.stateValues.numMinima).eq(1); - expect(f5.stateValues.numExtrema).eq(2); - expect(f5.stateValues.minima[0][0]).closeTo(Math.PI, 1e-6); - expect(f5.stateValues.minima[0][1]).eq(-1); - expect(f5.stateValues.maxima[0][0]).closeTo(2 * Math.PI, 1e-6); - expect(f5.stateValues.maxima[0][1]).eq(1); - expect(f5.stateValues.extrema[0][0]).closeTo(Math.PI, 1e-6); - expect(f5.stateValues.extrema[0][1]).eq(-1); - expect(f5.stateValues.extrema[1][0]).closeTo(2 * Math.PI, 1e-6); - expect(f5.stateValues.extrema[1][1]).eq(1); - - expect(f6.stateValues.numMaxima).eq(2); - expect(f6.stateValues.numMinima).eq(2); - expect(f6.stateValues.numExtrema).eq(4); - expect(f6.stateValues.minima[0][0]).closeTo(Math.PI, 1e-6); - expect(f6.stateValues.minima[0][1]).eq(0); - expect(f6.stateValues.minima[1][0]).closeTo(3 * Math.PI, 1e-6); - expect(f6.stateValues.minima[1][1]).eq(0); - expect(f6.stateValues.maxima[0][0]).closeTo(0, 1e-6); - expect(f6.stateValues.maxima[0][1]).eq(2); - expect(f6.stateValues.maxima[1][0]).closeTo(2 * Math.PI, 1e-6); - expect(f6.stateValues.maxima[1][1]).eq(2); - expect(f6.stateValues.extrema[0][0]).closeTo(0, 1e-6); - expect(f6.stateValues.extrema[0][1]).eq(2); - expect(f6.stateValues.extrema[1][0]).closeTo(Math.PI, 1e-6); - expect(f6.stateValues.extrema[1][1]).eq(0); - expect(f6.stateValues.extrema[2][0]).closeTo(2 * Math.PI, 1e-6); - expect(f6.stateValues.extrema[2][1]).eq(2); - expect(f6.stateValues.extrema[3][0]).closeTo(3 * Math.PI, 1e-6); - expect(f6.stateValues.extrema[3][1]).eq(0); - - expect(f7.stateValues.numMaxima).eq(2); - expect(f7.stateValues.numMinima).eq(1); - expect(f7.stateValues.numExtrema).eq(3); - expect(f7.stateValues.minima[0][0]).closeTo(2 * Math.PI, 1e-6); - expect(f7.stateValues.minima[0][1]).eq(3); - expect(f7.stateValues.maxima[0][0]).closeTo(Math.PI, 1e-6); - expect(f7.stateValues.maxima[0][1]).eq(5); - expect(f7.stateValues.maxima[1][0]).closeTo(3 * Math.PI, 1e-6); - expect(f7.stateValues.maxima[1][1]).eq(5); - expect(f7.stateValues.extrema[0][0]).closeTo(Math.PI, 1e-6); - expect(f7.stateValues.extrema[0][1]).eq(5); - expect(f7.stateValues.extrema[1][0]).closeTo(2 * Math.PI, 1e-6); - expect(f7.stateValues.extrema[1][1]).eq(3); - expect(f7.stateValues.extrema[2][0]).closeTo(3 * Math.PI, 1e-6); - expect(f7.stateValues.extrema[2][1]).eq(5); - - expect(f8.stateValues.numMaxima).eq(1); - expect(f8.stateValues.numMinima).eq(2); - expect(f8.stateValues.numExtrema).eq(3); - expect(f8.stateValues.minima[0][0]).closeTo(0, 1e-6); - expect(f8.stateValues.minima[0][1]).eq(4); - expect(f8.stateValues.minima[1][0]).closeTo(2 * Math.PI, 1e-6); - expect(f8.stateValues.minima[1][1]).eq(4); - expect(f8.stateValues.maxima[0][0]).closeTo(Math.PI, 1e-6); - expect(f8.stateValues.maxima[0][1]).eq(6); - expect(f8.stateValues.extrema[0][0]).closeTo(0, 1e-6); - expect(f8.stateValues.extrema[0][1]).eq(4); - expect(f8.stateValues.extrema[1][0]).closeTo(Math.PI, 1e-6); - expect(f8.stateValues.extrema[1][1]).eq(6); - expect(f8.stateValues.extrema[2][0]).closeTo(2 * Math.PI, 1e-6); - expect(f8.stateValues.extrema[2][1]).eq(4); - - let f9 = stateVariables["/f9"]; - let f10 = stateVariables["/f10"]; - let f11 = stateVariables["/f11"]; - let f12 = stateVariables["/f12"]; - expect(f9.stateValues.numMaxima).eq(1); - expect(f9.stateValues.numMinima).eq(1); - expect(f9.stateValues.numExtrema).eq(2); - expect(f9.stateValues.minima[0][0]).closeTo(-Math.PI, 1e-6); - expect(f9.stateValues.minima[0][1]).eq(-1); - expect(f9.stateValues.maxima[0][0]).closeTo(-2 * Math.PI, 1e-6); - expect(f9.stateValues.maxima[0][1]).eq(1); - expect(f9.stateValues.extrema[0][0]).closeTo(-2 * Math.PI, 1e-6); - expect(f9.stateValues.extrema[0][1]).eq(1); - expect(f9.stateValues.extrema[1][0]).closeTo(-Math.PI, 1e-6); - expect(f9.stateValues.extrema[1][1]).eq(-1); - - expect(f10.stateValues.numMaxima).eq(2); - expect(f10.stateValues.numMinima).eq(2); - expect(f10.stateValues.numExtrema).eq(4); - expect(f10.stateValues.minima[0][0]).closeTo(-3 * Math.PI, 1e-6); - expect(f10.stateValues.minima[0][1]).eq(0); - expect(f10.stateValues.minima[1][0]).closeTo(-Math.PI, 1e-6); - expect(f10.stateValues.minima[1][1]).eq(0); - expect(f10.stateValues.maxima[0][0]).closeTo(-2 * Math.PI, 1e-6); - expect(f10.stateValues.maxima[0][1]).eq(2); - expect(f10.stateValues.maxima[1][0]).closeTo(0, 1e-6); - expect(f10.stateValues.maxima[1][1]).eq(2); - expect(f10.stateValues.extrema[0][0]).closeTo(-3 * Math.PI, 1e-6); - expect(f10.stateValues.extrema[0][1]).eq(0); - expect(f10.stateValues.extrema[1][0]).closeTo(-2 * Math.PI, 1e-6); - expect(f10.stateValues.extrema[1][1]).eq(2); - expect(f10.stateValues.extrema[2][0]).closeTo(-Math.PI, 1e-6); - expect(f10.stateValues.extrema[2][1]).eq(0); - expect(f10.stateValues.extrema[3][0]).closeTo(0, 1e-6); - expect(f10.stateValues.extrema[3][1]).eq(2); - - expect(f11.stateValues.numMaxima).eq(1); - expect(f11.stateValues.numMinima).eq(2); - expect(f11.stateValues.numExtrema).eq(3); - expect(f11.stateValues.minima[0][0]).closeTo(-2 * Math.PI, 1e-6); - expect(f11.stateValues.minima[0][1]).eq(3); - expect(f11.stateValues.minima[1][0]).closeTo(0, 1e-6); - expect(f11.stateValues.minima[1][1]).eq(3); - expect(f11.stateValues.maxima[0][0]).closeTo(-Math.PI, 1e-6); - expect(f11.stateValues.maxima[0][1]).eq(5); - expect(f11.stateValues.extrema[0][0]).closeTo(-2 * Math.PI, 1e-6); - expect(f11.stateValues.extrema[0][1]).eq(3); - expect(f11.stateValues.extrema[1][0]).closeTo(-Math.PI, 1e-6); - expect(f11.stateValues.extrema[1][1]).eq(5); - expect(f11.stateValues.extrema[2][0]).closeTo(0, 1e-6); - expect(f11.stateValues.extrema[2][1]).eq(3); - - expect(f12.stateValues.numMaxima).eq(2); - expect(f12.stateValues.numMinima).eq(1); - expect(f12.stateValues.numExtrema).eq(3); - expect(f12.stateValues.minima[0][0]).closeTo(-2 * Math.PI, 1e-6); - expect(f12.stateValues.minima[0][1]).eq(4); - expect(f12.stateValues.maxima[0][0]).closeTo(-3 * Math.PI, 1e-6); - expect(f12.stateValues.maxima[0][1]).eq(6); - expect(f12.stateValues.maxima[1][0]).closeTo(-Math.PI, 1e-6); - expect(f12.stateValues.maxima[1][1]).eq(6); - expect(f12.stateValues.extrema[0][0]).closeTo(-3 * Math.PI, 1e-6); - expect(f12.stateValues.extrema[0][1]).eq(6); - expect(f12.stateValues.extrema[1][0]).closeTo(-2 * Math.PI, 1e-6); - expect(f12.stateValues.extrema[1][1]).eq(4); - expect(f12.stateValues.extrema[2][0]).closeTo(-Math.PI, 1e-6); - expect(f12.stateValues.extrema[2][1]).eq(6); - }); - }); - - it("extrema at domain endpoints, interpolated function", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - -

$f1.extrema{assignNames="f1e1 f1e2 f1e3"}

-

$f2.extrema{assignNames="f2e1 f2e2 f2e3 f2e4 f2e5"}

-

$f3.extrema{assignNames="f3e1 f3e2 f3e3"}

- - - - - - -

$f4.extrema{assignNames="f4e1 f4e2 f4e3"}

-

$f5.extrema{assignNames="f5e1 f5e2 f5e3 f5e4 f5e5"}

-

$f6.extrema{assignNames="f6e1 f6e2 f6e3"}

- - - - - - -

$f7.extrema{assignNames="f7e1 f7e2 f7e3"}

-

$f8.extrema{assignNames="f8e1 f8e2 f8e3 f8e4 f8e5"}

-

$f9.extrema{assignNames="f9e1 f9e2 f9e3"}

- - `, - }, - "*", - ); - }); - - let extremax1 = [0, 1 / 3, 2 / 3, 1].map( - (a) => -Math.sqrt(2) * (1 - a) + Math.sqrt(10) * a, - ); - let extremax2 = [0, 1 / 3, 2 / 3, 1].map((a) => Math.sqrt(10) * a); - let extremax3 = [0, 1 / 3, 2 / 3, 1].map( - (a) => -Math.sqrt(2) * (1 - a), - ); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/f1e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(extremax1[1] * 10 ** 5) / 10 ** 5, - )},${nInDOM( - Math.round((Math.sqrt(3) - 1) * 10 ** 5) / 10 ** 5, - )})`, - ); - }); - cy.get(cesc("#\\/f1e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(extremax1[2] * 10 ** 5) / 10 ** 5, - )},${nInDOM( - Math.round((Math.sqrt(11) + 1) * 10 ** 5) / 10 ** 5, - )})`, - ); - }); - cy.get(cesc("#\\/f1e3")).should("not.exist"); - - cy.get(cesc("#\\/f2e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(extremax1[0] * 10 ** 5) / 10 ** 5, - )},${nInDOM( - Math.round((Math.sqrt(3) + 1) * 10 ** 5) / 10 ** 5, - )})`, - ); - }); - cy.get(cesc("#\\/f2e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(extremax1[1] * 10 ** 5) / 10 ** 5, - )},${nInDOM( - Math.round(Math.sqrt(3) * 10 ** 5) / 10 ** 5, - )})`, - ); - }); - cy.get(cesc("#\\/f2e3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(extremax1[2] * 10 ** 5) / 10 ** 5, - )},${nInDOM( - Math.round((Math.sqrt(11) + 2) * 10 ** 5) / 10 ** 5, - )})`, - ); - }); - cy.get(cesc("#\\/f2e4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(extremax1[3] * 10 ** 5) / 10 ** 5, - )},${nInDOM( - Math.round((Math.sqrt(11) + 1) * 10 ** 5) / 10 ** 5, - )})`, - ); - }); - cy.get(cesc("#\\/f2e5")).should("not.exist"); - - cy.get(cesc("#\\/f3e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(extremax1[1] * 10 ** 5) / 10 ** 5, - )},${nInDOM( - Math.round((Math.sqrt(3) + 1) * 10 ** 5) / 10 ** 5, - )})`, - ); - }); - cy.get(cesc("#\\/f3e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(extremax1[2] * 10 ** 5) / 10 ** 5, - )},${nInDOM( - Math.round((Math.sqrt(11) + 3) * 10 ** 5) / 10 ** 5, - )})`, - ); - }); - cy.get(cesc("#\\/f3e3")).should("not.exist"); - - cy.get(cesc("#\\/f4e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(extremax2[1] * 10 ** 5) / 10 ** 5, - )},${nInDOM( - Math.round((Math.sqrt(3) - 1) * 10 ** 5) / 10 ** 5, - )})`, - ); - }); - cy.get(cesc("#\\/f4e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(extremax2[2] * 10 ** 5) / 10 ** 5, - )},${nInDOM( - Math.round((Math.sqrt(11) + 1) * 10 ** 5) / 10 ** 5, - )})`, - ); - }); - cy.get(cesc("#\\/f4e3")).should("not.exist"); - - cy.get(cesc("#\\/f5e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(extremax2[0] * 10 ** 5) / 10 ** 5, - )},${nInDOM( - Math.round((Math.sqrt(3) + 1) * 10 ** 5) / 10 ** 5, - )})`, - ); - }); - cy.get(cesc("#\\/f5e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(extremax2[1] * 10 ** 5) / 10 ** 5, - )},${nInDOM( - Math.round(Math.sqrt(3) * 10 ** 5) / 10 ** 5, - )})`, - ); - }); - cy.get(cesc("#\\/f5e3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(extremax2[2] * 10 ** 5) / 10 ** 5, - )},${nInDOM( - Math.round((Math.sqrt(11) + 2) * 10 ** 5) / 10 ** 5, - )})`, - ); - }); - cy.get(cesc("#\\/f5e4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(extremax2[3] * 10 ** 5) / 10 ** 5, - )},${nInDOM( - Math.round((Math.sqrt(11) + 1) * 10 ** 5) / 10 ** 5, - )})`, - ); - }); - cy.get(cesc("#\\/f5e5")).should("not.exist"); - - cy.get(cesc("#\\/f6e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(extremax2[1] * 10 ** 5) / 10 ** 5, - )},${nInDOM( - Math.round((Math.sqrt(3) + 1) * 10 ** 5) / 10 ** 5, - )})`, - ); - }); - cy.get(cesc("#\\/f6e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(extremax2[2] * 10 ** 5) / 10 ** 5, - )},${nInDOM( - Math.round((Math.sqrt(11) + 3) * 10 ** 5) / 10 ** 5, - )})`, - ); - }); - cy.get(cesc("#\\/f6e3")).should("not.exist"); - - cy.get(cesc("#\\/f7e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(extremax3[1] * 10 ** 5) / 10 ** 5, - )},${nInDOM( - Math.round((Math.sqrt(3) - 1) * 10 ** 5) / 10 ** 5, - )})`, - ); - }); - cy.get(cesc("#\\/f7e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(extremax3[2] * 10 ** 5) / 10 ** 5, - )},${nInDOM( - Math.round((Math.sqrt(11) + 1) * 10 ** 5) / 10 ** 5, - )})`, - ); - }); - cy.get(cesc("#\\/f7e3")).should("not.exist"); - - cy.get(cesc("#\\/f8e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(extremax3[0] * 10 ** 5) / 10 ** 5, - )},${nInDOM( - Math.round((Math.sqrt(3) + 1) * 10 ** 5) / 10 ** 5, - )})`, - ); - }); - cy.get(cesc("#\\/f8e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(extremax3[1] * 10 ** 5) / 10 ** 5, - )},${nInDOM( - Math.round(Math.sqrt(3) * 10 ** 5) / 10 ** 5, - )})`, - ); - }); - cy.get(cesc("#\\/f8e3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(extremax3[2] * 10 ** 5) / 10 ** 5, - )},${nInDOM( - Math.round((Math.sqrt(11) + 2) * 10 ** 5) / 10 ** 5, - )})`, - ); - }); - cy.get(cesc("#\\/f8e4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(extremax3[3] * 10 ** 5) / 10 ** 5, - )},${nInDOM( - Math.round((Math.sqrt(11) + 1) * 10 ** 5) / 10 ** 5, - )})`, - ); - }); - cy.get(cesc("#\\/f8e5")).should("not.exist"); - - cy.get(cesc("#\\/f9e1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(extremax3[1] * 10 ** 5) / 10 ** 5, - )},${nInDOM( - Math.round((Math.sqrt(3) + 1) * 10 ** 5) / 10 ** 5, - )})`, - ); - }); - cy.get(cesc("#\\/f9e2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq( - `(${nInDOM( - Math.round(extremax3[2] * 10 ** 5) / 10 ** 5, - )},${nInDOM( - Math.round((Math.sqrt(11) + 3) * 10 ** 5) / 10 ** 5, - )})`, - ); - }); - cy.get(cesc("#\\/f9e3")).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let f1 = stateVariables["/f1"]; - let f2 = stateVariables["/f2"]; - let f3 = stateVariables["/f3"]; - expect(f1.stateValues.numMaxima).eq(1); - expect(f1.stateValues.numMinima).eq(1); - expect(f1.stateValues.numExtrema).eq(2); - expect(f1.stateValues.minima[0][0]).closeTo(extremax1[1], 1e-12); - expect(f1.stateValues.minima[0][1]).closeTo( - Math.sqrt(3) - 1, - 1e-12, - ); - expect(f1.stateValues.maxima[0][0]).closeTo(extremax1[2], 1e-12); - expect(f1.stateValues.maxima[0][1]).closeTo( - Math.sqrt(11) + 1, - 1e-12, - ); - expect(f1.stateValues.extrema[0][0]).closeTo(extremax1[1], 1e-12); - expect(f1.stateValues.extrema[0][1]).closeTo( - Math.sqrt(3) - 1, - 1e-12, - ); - expect(f1.stateValues.extrema[1][0]).closeTo(extremax1[2], 1e-12); - expect(f1.stateValues.extrema[1][1]).closeTo( - Math.sqrt(11) + 1, - 1e-12, - ); - - expect(f2.stateValues.numMaxima).eq(2); - expect(f2.stateValues.numMinima).eq(2); - expect(f2.stateValues.numExtrema).eq(4); - expect(f2.stateValues.minima[0][0]).closeTo(extremax1[1], 1e-12); - expect(f2.stateValues.minima[0][1]).closeTo(Math.sqrt(3), 1e-12); - expect(f2.stateValues.minima[1][0]).closeTo(extremax1[3], 1e-12); - expect(f2.stateValues.minima[1][1]).closeTo( - Math.sqrt(11) + 1, - 1e-12, - ); - expect(f2.stateValues.maxima[0][0]).closeTo(extremax1[0], 1e-12); - expect(f2.stateValues.maxima[0][1]).closeTo( - Math.sqrt(3) + 1, - 1e-12, - ); - expect(f2.stateValues.maxima[1][0]).closeTo(extremax1[2], 1e-12); - expect(f2.stateValues.maxima[1][1]).closeTo( - Math.sqrt(11) + 2, - 1e-12, - ); - expect(f2.stateValues.extrema[0][0]).closeTo(extremax1[0], 1e-12); - expect(f2.stateValues.extrema[0][1]).closeTo( - Math.sqrt(3) + 1, - 1e-12, - ); - expect(f2.stateValues.extrema[1][0]).closeTo(extremax1[1], 1e-12); - expect(f2.stateValues.extrema[1][1]).closeTo(Math.sqrt(3), 1e-12); - expect(f2.stateValues.extrema[2][0]).closeTo(extremax1[2], 1e-12); - expect(f2.stateValues.extrema[2][1]).closeTo( - Math.sqrt(11) + 2, - 1e-12, - ); - expect(f2.stateValues.extrema[3][0]).closeTo(extremax1[3], 1e-12); - expect(f2.stateValues.extrema[3][1]).closeTo( - Math.sqrt(11) + 1, - 1e-12, - ); - - expect(f3.stateValues.numMaxima).eq(1); - expect(f3.stateValues.numMinima).eq(1); - expect(f3.stateValues.numExtrema).eq(2); - expect(f3.stateValues.minima[0][0]).closeTo(extremax1[1], 1e-12); - expect(f3.stateValues.minima[0][1]).closeTo( - Math.sqrt(3) + 1, - 1e-12, - ); - expect(f3.stateValues.maxima[0][0]).closeTo(extremax1[2], 1e-12); - expect(f3.stateValues.maxima[0][1]).closeTo( - Math.sqrt(11) + 3, - 1e-12, - ); - expect(f3.stateValues.extrema[0][0]).closeTo(extremax1[1], 1e-12); - expect(f3.stateValues.extrema[0][1]).closeTo( - Math.sqrt(3) + 1, - 1e-12, - ); - expect(f3.stateValues.extrema[1][0]).closeTo(extremax1[2], 1e-12); - expect(f3.stateValues.extrema[1][1]).closeTo( - Math.sqrt(11) + 3, - 1e-12, - ); - - let f4 = stateVariables["/f4"]; - let f5 = stateVariables["/f5"]; - let f6 = stateVariables["/f6"]; - expect(f4.stateValues.numMaxima).eq(1); - expect(f4.stateValues.numMinima).eq(1); - expect(f4.stateValues.numExtrema).eq(2); - expect(f4.stateValues.minima[0][0]).closeTo(extremax2[1], 1e-12); - expect(f4.stateValues.minima[0][1]).closeTo( - Math.sqrt(3) - 1, - 1e-12, - ); - expect(f4.stateValues.maxima[0][0]).closeTo(extremax2[2], 1e-12); - expect(f4.stateValues.maxima[0][1]).closeTo( - Math.sqrt(11) + 1, - 1e-12, - ); - expect(f4.stateValues.extrema[0][0]).closeTo(extremax2[1], 1e-12); - expect(f4.stateValues.extrema[0][1]).closeTo( - Math.sqrt(3) - 1, - 1e-12, - ); - expect(f4.stateValues.extrema[1][0]).closeTo(extremax2[2], 1e-12); - expect(f4.stateValues.extrema[1][1]).closeTo( - Math.sqrt(11) + 1, - 1e-12, - ); - - expect(f5.stateValues.numMaxima).eq(2); - expect(f5.stateValues.numMinima).eq(2); - expect(f5.stateValues.numExtrema).eq(4); - expect(f5.stateValues.minima[0][0]).closeTo(extremax2[1], 1e-12); - expect(f5.stateValues.minima[0][1]).closeTo(Math.sqrt(3), 1e-12); - expect(f5.stateValues.minima[1][0]).closeTo(extremax2[3], 1e-12); - expect(f5.stateValues.minima[1][1]).closeTo( - Math.sqrt(11) + 1, - 1e-12, - ); - expect(f5.stateValues.maxima[0][0]).closeTo(extremax2[0], 1e-12); - expect(f5.stateValues.maxima[0][1]).closeTo( - Math.sqrt(3) + 1, - 1e-12, - ); - expect(f5.stateValues.maxima[1][0]).closeTo(extremax2[2], 1e-12); - expect(f5.stateValues.maxima[1][1]).closeTo( - Math.sqrt(11) + 2, - 1e-12, - ); - expect(f5.stateValues.extrema[0][0]).closeTo(extremax2[0], 1e-12); - expect(f5.stateValues.extrema[0][1]).closeTo( - Math.sqrt(3) + 1, - 1e-12, - ); - expect(f5.stateValues.extrema[1][0]).closeTo(extremax2[1], 1e-12); - expect(f5.stateValues.extrema[1][1]).closeTo(Math.sqrt(3), 1e-12); - expect(f5.stateValues.extrema[2][0]).closeTo(extremax2[2], 1e-12); - expect(f5.stateValues.extrema[2][1]).closeTo( - Math.sqrt(11) + 2, - 1e-12, - ); - expect(f5.stateValues.extrema[3][0]).closeTo(extremax2[3], 1e-12); - expect(f5.stateValues.extrema[3][1]).closeTo( - Math.sqrt(11) + 1, - 1e-12, - ); - - expect(f6.stateValues.numMaxima).eq(1); - expect(f6.stateValues.numMinima).eq(1); - expect(f6.stateValues.numExtrema).eq(2); - expect(f6.stateValues.minima[0][0]).closeTo(extremax2[1], 1e-12); - expect(f6.stateValues.minima[0][1]).closeTo( - Math.sqrt(3) + 1, - 1e-12, - ); - expect(f6.stateValues.maxima[0][0]).closeTo(extremax2[2], 1e-12); - expect(f6.stateValues.maxima[0][1]).closeTo( - Math.sqrt(11) + 3, - 1e-12, - ); - expect(f6.stateValues.extrema[0][0]).closeTo(extremax2[1], 1e-12); - expect(f6.stateValues.extrema[0][1]).closeTo( - Math.sqrt(3) + 1, - 1e-12, - ); - expect(f6.stateValues.extrema[1][0]).closeTo(extremax2[2], 1e-12); - expect(f6.stateValues.extrema[1][1]).closeTo( - Math.sqrt(11) + 3, - 1e-12, - ); - - let f7 = stateVariables["/f7"]; - let f8 = stateVariables["/f8"]; - let f9 = stateVariables["/f9"]; - expect(f7.stateValues.numMaxima).eq(1); - expect(f7.stateValues.numMinima).eq(1); - expect(f7.stateValues.numExtrema).eq(2); - expect(f7.stateValues.minima[0][0]).closeTo(extremax3[1], 1e-12); - expect(f7.stateValues.minima[0][1]).closeTo( - Math.sqrt(3) - 1, - 1e-12, - ); - expect(f7.stateValues.maxima[0][0]).closeTo(extremax3[2], 1e-12); - expect(f7.stateValues.maxima[0][1]).closeTo( - Math.sqrt(11) + 1, - 1e-12, - ); - expect(f7.stateValues.extrema[0][0]).closeTo(extremax3[1], 1e-12); - expect(f7.stateValues.extrema[0][1]).closeTo( - Math.sqrt(3) - 1, - 1e-12, - ); - expect(f7.stateValues.extrema[1][0]).closeTo(extremax3[2], 1e-12); - expect(f7.stateValues.extrema[1][1]).closeTo( - Math.sqrt(11) + 1, - 1e-12, - ); - - expect(f8.stateValues.numMaxima).eq(2); - expect(f8.stateValues.numMinima).eq(2); - expect(f8.stateValues.numExtrema).eq(4); - expect(f8.stateValues.minima[0][0]).closeTo(extremax3[1], 1e-12); - expect(f8.stateValues.minima[0][1]).closeTo(Math.sqrt(3), 1e-12); - expect(f8.stateValues.minima[1][0]).closeTo(extremax3[3], 1e-12); - expect(f8.stateValues.minima[1][1]).closeTo( - Math.sqrt(11) + 1, - 1e-12, - ); - expect(f8.stateValues.maxima[0][0]).closeTo(extremax3[0], 1e-12); - expect(f8.stateValues.maxima[0][1]).closeTo( - Math.sqrt(3) + 1, - 1e-12, - ); - expect(f8.stateValues.maxima[1][0]).closeTo(extremax3[2], 1e-12); - expect(f8.stateValues.maxima[1][1]).closeTo( - Math.sqrt(11) + 2, - 1e-12, - ); - expect(f8.stateValues.extrema[0][0]).closeTo(extremax3[0], 1e-12); - expect(f8.stateValues.extrema[0][1]).closeTo( - Math.sqrt(3) + 1, - 1e-12, - ); - expect(f8.stateValues.extrema[1][0]).closeTo(extremax3[1], 1e-12); - expect(f8.stateValues.extrema[1][1]).closeTo(Math.sqrt(3), 1e-12); - expect(f8.stateValues.extrema[2][0]).closeTo(extremax3[2], 1e-12); - expect(f8.stateValues.extrema[2][1]).closeTo( - Math.sqrt(11) + 2, - 1e-12, - ); - expect(f8.stateValues.extrema[3][0]).closeTo(extremax3[3], 1e-12); - expect(f8.stateValues.extrema[3][1]).closeTo( - Math.sqrt(11) + 1, - 1e-12, - ); - - expect(f9.stateValues.numMaxima).eq(1); - expect(f9.stateValues.numMinima).eq(1); - expect(f9.stateValues.numExtrema).eq(2); - expect(f9.stateValues.minima[0][0]).closeTo(extremax3[1], 1e-12); - expect(f9.stateValues.minima[0][1]).closeTo( - Math.sqrt(3) + 1, - 1e-12, - ); - expect(f9.stateValues.maxima[0][0]).closeTo(extremax3[2], 1e-12); - expect(f9.stateValues.maxima[0][1]).closeTo( - Math.sqrt(11) + 3, - 1e-12, - ); - expect(f9.stateValues.extrema[0][0]).closeTo(extremax3[1], 1e-12); - expect(f9.stateValues.extrema[0][1]).closeTo( - Math.sqrt(3) + 1, - 1e-12, - ); - expect(f9.stateValues.extrema[1][0]).closeTo(extremax3[2], 1e-12); - expect(f9.stateValues.extrema[1][1]).closeTo( - Math.sqrt(11) + 3, - 1e-12, - ); - }); - }); - - it("two functions with mutual dependence", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (1,2) - (3,4) - (-5,7) - (8,-1) - - - - - -

Number of maxima:

-

Number of minima:

- -

$_function1.maximumLocations

-

$_function1.maximumValues

-

$_function1.minimumLocations

-

$_function1.minimumValues

-

$_function1.extremumLocations

-

$_function1.extremumValues

- - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let f1 = stateVariables["/_function1"]; - let f2 = stateVariables["/_function2"]; - expect(await f1.stateValues.numMaxima).eq(1); - expect(await f1.stateValues.numMinima).eq(2); - expect(await f1.stateValues.numExtrema).eq(3); - expect(await f2.stateValues.numMaxima).eq(2); - expect(await f2.stateValues.numMinima).eq(1); - expect(await f2.stateValues.numExtrema).eq(3); - - expect(await f1.stateValues.maximumLocations).eq(2); - expect(await f1.stateValues.maximumValues).eq(1); - - expect(await f1.stateValues.xscale).eq(1); - expect(await f1.stateValues.yscale).eq(5); - expect(await f2.stateValues.xscale).eq(1); - expect(await f2.stateValues.yscale).eq(5); - }); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "2"); - cy.get(cesc("#\\/numMinima")).should("have.text", "1"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 2, y: 6 }, - }); - - let stateVariables = await win.returnAllStateVariables1(); - - let f1 = stateVariables["/_function1"]; - let f2 = stateVariables["/_function2"]; - expect(await f1.stateValues.numMaxima).eq(1); - expect(await f1.stateValues.numMinima).eq(2); - expect(await f1.stateValues.numExtrema).eq(3); - expect(await f2.stateValues.numMaxima).eq(1); - expect(await f2.stateValues.numMinima).eq(0); - expect(await f2.stateValues.numExtrema).eq(1); - - expect(await f1.stateValues.maximumLocations).eq(1); - expect(await f1.stateValues.maximumValues).eq(0); - }); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "1"); - cy.get(cesc("#\\/numMinima")).should("have.text", "0"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point2", - args: { x: 3, y: 7 }, - }); - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point3", - args: { x: 9, y: 0 }, - }); - - let stateVariables = await win.returnAllStateVariables1(); - - let f1 = stateVariables["/_function1"]; - let f2 = stateVariables["/_function2"]; - expect(await f1.stateValues.numMaxima).eq(1); - expect(await f1.stateValues.numMinima).eq(2); - expect(await f1.stateValues.numExtrema).eq(3); - expect(await f2.stateValues.numMaxima).eq(2); - expect(await f2.stateValues.numMinima).eq(2); - expect(await f2.stateValues.numExtrema).eq(4); - - expect(await f1.stateValues.maximumLocations).eq(2); - expect(await f1.stateValues.maximumValues).eq(2); - }); - - cy.get(cesc("#\\/numMaxima")).should("have.text", "2"); - cy.get(cesc("#\\/numMinima")).should("have.text", "2"); - }); - - it("shadowed works correctly with initially unresolved", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - $_mathinput2 x^3+1 - - - $_function1{name="f1a"} - -

$f1a.xscale

-

$_function1.xscale

- - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/_p1")).should("have.text", "NaN"); - cy.get(cesc("#\\/_p2")).should("have.text", "NaN"); - - cy.get(cesc("#\\/_function1")).should("contain.text", "_x3+1"); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type("1{enter}", { - force: true, - }); - cy.get(cesc("#\\/_mathinput2") + " textarea").type("2{enter}", { - force: true, - }); - - cy.get(cesc("#\\/_function1")).should("contain.text", "2x3+1"); - - cy.get(cesc("#\\/_p1")).should("have.text", "1"); - cy.get(cesc("#\\/_p2")).should("have.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(-2)).eq(2 * (-2) ** 3 + 1); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{end}{backspace}3{enter}", - { force: true }, - ); - cy.get(cesc("#\\/_mathinput2") + " textarea").type( - "{end}{backspace}4{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/_function1")).should("contain.text", "4x3+1"); - - cy.get(cesc("#\\/_p1")).should("have.text", "3"); - cy.get(cesc("#\\/_p2")).should("have.text", "3"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - expect(f(-2)).eq(4 * (-2) ** 3 + 1); - }); - }); - - it("extrema of quartic, copied multiple times", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - $_mathinput1 x^4 + $_mathinput2 x^3 +$_mathinput3 x^2 +1 - - - $_function1{name="f1a"} - - - - - - - $f1a{name="f1b"} - $f1b.extremum1{assignNames="extremum1"} - $f1b.extremum2{assignNames="extremum2"} - $f1b.extremum3{assignNames="extremum3"} - - - - - $_mathinput1.value{assignNames="m1"} - $_mathinput2.value{assignNames="m2"} - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let max1 = stateVariables["/maximum1"].stateValues.coords; - expect(max1[1]).closeTo(0, 0.00001); - expect(max1[2]).closeTo(1, 0.00001); - expect(stateVariables["/maximum2"]).eq(undefined); - - let min1 = stateVariables["/minimum1"].stateValues.coords; - expect(min1[1]).closeTo(-1, 0.00001); - expect(min1[2]).closeTo(0, 0.00001); - let min2 = stateVariables["/minimum2"].stateValues.coords; - expect(min2[1]).closeTo(1, 0.00001); - expect(min2[2]).closeTo(0, 0.00001); - expect(stateVariables["/minimum3"]).eq(undefined); - - expect(stateVariables["/extremum1"].stateValues.coords).eqls(min1); - expect(stateVariables["/extremum2"].stateValues.coords).eqls(max1); - expect(stateVariables["/extremum3"].stateValues.coords).eqls(min2); - expect(stateVariables["/globalmin"].stateValues.coords).eqls(min1); - expect(stateVariables["/globalinf"].stateValues.coords).eqls(min1); - expect(stateVariables["/globalmax"]).eq(undefined); - expect(stateVariables["/globalsup"].stateValues.xs[1]).greaterThan( - 1e6, - ); - }); - - cy.get(cesc("#\\/_mathinput2") + " textarea").type( - "{end}{backspace}2{enter}", - { force: true }, - ); - cy.get(cesc("#\\/m2")).should("contain.text", "2"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let max1 = stateVariables["/maximum1"].stateValues.coords; - expect(max1[1]).closeTo(0, 0.00001); - expect(max1[2]).closeTo(1, 0.00001); - expect(stateVariables["/maximum2"]).eq(undefined); - - let min1 = stateVariables["/minimum1"].stateValues.coords; - expect(min1[1]).closeTo(-2, 0.00001); - expect(min1[2]).closeTo(-7, 0.00001); - let min2 = stateVariables["/minimum2"].stateValues.coords; - expect(min2[1]).closeTo(0.5, 0.00001); - expect(min2[2]).closeTo(13 / 16, 0.00001); - expect(stateVariables["/minimum3"]).eq(undefined); - - expect(stateVariables["/extremum1"].stateValues.coords).eqls(min1); - expect(stateVariables["/extremum2"].stateValues.coords).eqls(max1); - expect(stateVariables["/extremum3"].stateValues.coords).eqls(min2); - expect(stateVariables["/globalmin"].stateValues.coords).eqls(min1); - expect(stateVariables["/globalinf"].stateValues.coords).eqls(min1); - expect(stateVariables["/globalmax"]).eq(undefined); - expect(stateVariables["/globalsup"].stateValues.xs[1]).greaterThan( - 1e6, - ); - }); - - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - "{end}{backspace}-1{enter}", - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "−1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let max1 = stateVariables["/maximum1"].stateValues.coords; - expect(max1[1]).closeTo(0, 0.00001); - expect(max1[2]).closeTo(1, 0.00001); - expect(stateVariables["/maximum2"]).eq(undefined); - - expect(stateVariables["/minimum1"]).eq(undefined); - - expect(stateVariables["/extremum1"].stateValues.coords).eqls(max1); - expect(stateVariables["/extremum2"]).eq(undefined); - expect(stateVariables["/extremum3"]).eq(undefined); - expect(stateVariables["/globalmax"].stateValues.coords).eqls(max1); - expect(stateVariables["/globalsup"].stateValues.coords).eqls(max1); - expect(stateVariables["/globalmin"]).eq(undefined); - expect(stateVariables["/globalinf"].stateValues.xs[1]).lessThan( - -1e6, - ); - }); - }); - - it("function of function formula can redefine variable", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - st^3 - - $f - $f.formula - - $f{name="f4"} - $f2{name="f5"} - $f3{name="f6"} - - $f.variable{assignNames="fv"} - $f2.variable{assignNames="f2v"} - $f3.variable{assignNames="f3v"} - $f4.variable{assignNames="f4v"} - $f5.variable{assignNames="f5v"} - $f6.variable{assignNames="f6v"} - -

$$f(u)

-

$$f2(u)

-

$$f3(u)

-

$$f4(u)

-

$$f5(u)

-

$$f6(u)

- - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/fv")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("t"); - }); - cy.get(cesc("#\\/f2v")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("t"); - }); - cy.get(cesc("#\\/f3v")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("s"); - }); - cy.get(cesc("#\\/f4v")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("t"); - }); - cy.get(cesc("#\\/f5v")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("t"); - }); - cy.get(cesc("#\\/f6v")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("s"); - }); - cy.get(cesc("#\\/fOfu")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("su3"); - }); - cy.get(cesc("#\\/f2Ofu")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("su3"); - }); - cy.get(cesc("#\\/f3Ofu")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("ut3"); - }); - cy.get(cesc("#\\/f4Ofu")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("su3"); - }); - cy.get(cesc("#\\/f5Ofu")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("su3"); - }); - cy.get(cesc("#\\/f6Ofu")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("ut3"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/f"].stateValues.variables[0]).eq("t"); - expect(stateVariables["/f2"].stateValues.variables[0]).eq("t"); - expect(stateVariables["/f3"].stateValues.variables[0]).eq("s"); - expect(stateVariables["/f4"].stateValues.variables[0]).eq("t"); - expect(stateVariables["/f5"].stateValues.variables[0]).eq("t"); - expect(stateVariables["/f6"].stateValues.variables[0]).eq("s"); - - expect(stateVariables["/f"].stateValues.formula).eqls([ - "*", - "s", - ["^", "t", 3], - ]); - expect(stateVariables["/f2"].stateValues.formula).eqls([ - "*", - "s", - ["^", "t", 3], - ]); - expect(stateVariables["/f3"].stateValues.formula).eqls([ - "*", - "s", - ["^", "t", 3], - ]); - expect(stateVariables["/f4"].stateValues.formula).eqls([ - "*", - "s", - ["^", "t", 3], - ]); - expect(stateVariables["/f5"].stateValues.formula).eqls([ - "*", - "s", - ["^", "t", 3], - ]); - expect(stateVariables["/f6"].stateValues.formula).eqls([ - "*", - "s", - ["^", "t", 3], - ]); - - expect( - stateVariables[ - stateVariables["/fOfu"].activeChildren[0].componentName - ].stateValues.value, - ).eqls(["*", "s", ["^", "u", 3]]); - expect( - stateVariables[ - stateVariables["/f2Ofu"].activeChildren[0].componentName - ].stateValues.value, - ).eqls(["*", "s", ["^", "u", 3]]); - expect( - stateVariables[ - stateVariables["/f3Ofu"].activeChildren[0].componentName - ].stateValues.value, - ).eqls(["*", "u", ["^", "t", 3]]); - expect( - stateVariables[ - stateVariables["/f4Ofu"].activeChildren[0].componentName - ].stateValues.value, - ).eqls(["*", "s", ["^", "u", 3]]); - expect( - stateVariables[ - stateVariables["/f5Ofu"].activeChildren[0].componentName - ].stateValues.value, - ).eqls(["*", "s", ["^", "u", 3]]); - expect( - stateVariables[ - stateVariables["/f6Ofu"].activeChildren[0].componentName - ].stateValues.value, - ).eqls(["*", "u", ["^", "t", 3]]); - }); - }); - - it("function of interpolated function can redefine variable without changing function", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - $f - $f - - $f{name="f4"} - $f2{name="f5"} - $f3{name="f6"} - - $f.variable{assignNames="fv"} - $f2.variable{assignNames="f2v"} - $f3.variable{assignNames="f3v"} - $f4.variable{assignNames="f4v"} - $f5.variable{assignNames="f5v"} - $f6.variable{assignNames="f6v"} - -

$$f(0)

-

$$f2(0)

-

$$f3(0)

-

$$f4(0)

-

$$f5(0)

-

$$f6(0)

- -

$$f(1)

-

$$f2(1)

-

$$f3(1)

-

$$f4(1)

-

$$f5(1)

-

$$f6(1)

- -

$$f(2)

-

$$f2(2)

-

$$f3(2)

-

$$f4(2)

-

$$f5(2)

-

$$f6(2)

- - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/fv")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/f2v")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/f3v")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("s"); - }); - cy.get(cesc("#\\/f4v")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/f5v")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/f6v")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("s"); - }); - cy.get(cesc("#\\/fOf0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/f2Of0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/f3Of0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/f4Of0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/f5Of0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/f6Of0")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2"); - }); - cy.get(cesc("#\\/fOf1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/f2Of1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/f3Of1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/f4Of1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/f5Of1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/f6Of1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(cesc("#\\/fOf2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6"); - }); - cy.get(cesc("#\\/f2Of2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6"); - }); - cy.get(cesc("#\\/f3Of2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6"); - }); - cy.get(cesc("#\\/f4Of2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6"); - }); - cy.get(cesc("#\\/f5Of2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6"); - }); - cy.get(cesc("#\\/f6Of2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6"); - }); - }); - - // Don't have a way to test this anymore. Should we send this info via a message? - it.skip("extrema not resolved if not requested", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - sin(x) - $f{name="f2"} - $f - - $g{name="g2"} - $g - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/f"].state.formula.isResolved).eq(true); - expect(stateVariables["/f"].state.symbolicfs.isResolved).eq(false); - expect(stateVariables["/f"].state.numericalfs.isResolved).eq(false); - expect(stateVariables["/f"].state.allMaxima.isResolved).eq(false); - expect(stateVariables["/f"].state.allMinima.isResolved).eq(false); - expect(stateVariables["/f"].state.allExtrema.isResolved).eq(false); - expect(stateVariables["/f"].state.numMaxima.isResolved).eq(false); - expect(stateVariables["/f"].state.numMinima.isResolved).eq(false); - expect(stateVariables["/f"].state.numExtrema.isResolved).eq(false); - expect(stateVariables["/f"].state.maxima.isResolved).eq(false); - expect(stateVariables["/f"].state.minima.isResolved).eq(false); - expect(stateVariables["/f"].state.extrema.isResolved).eq(false); - - expect(stateVariables["/f2"].state.formula.isResolved).eq(true); - expect(stateVariables["/f2"].state.symbolicfs.isResolved).eq(false); - expect(stateVariables["/f2"].state.numericalfs.isResolved).eq( - false, - ); - expect(stateVariables["/f2"].state.allMaxima.isResolved).eq(false); - expect(stateVariables["/f2"].state.allMinima.isResolved).eq(false); - expect(stateVariables["/f2"].state.allExtrema.isResolved).eq(false); - expect(stateVariables["/f2"].state.numMaxima.isResolved).eq(false); - expect(stateVariables["/f2"].state.numMinima.isResolved).eq(false); - expect(stateVariables["/f2"].state.numExtrema.isResolved).eq(false); - expect(stateVariables["/f2"].state.maxima.isResolved).eq(false); - expect(stateVariables["/f2"].state.minima.isResolved).eq(false); - expect(stateVariables["/f2"].state.extrema.isResolved).eq(false); - - expect(stateVariables["/f3"].state.formula.isResolved).eq(true); - expect(stateVariables["/f3"].state.symbolicfs.isResolved).eq(false); - expect(stateVariables["/f3"].state.numericalfs.isResolved).eq( - false, - ); - expect(stateVariables["/f3"].state.allMaxima.isResolved).eq(false); - expect(stateVariables["/f3"].state.allMinima.isResolved).eq(false); - expect(stateVariables["/f3"].state.allExtrema.isResolved).eq(false); - expect(stateVariables["/f3"].state.numMaxima.isResolved).eq(false); - expect(stateVariables["/f3"].state.numMinima.isResolved).eq(false); - expect(stateVariables["/f3"].state.numExtrema.isResolved).eq(false); - expect(stateVariables["/f3"].state.maxima.isResolved).eq(false); - expect(stateVariables["/f3"].state.minima.isResolved).eq(false); - expect(stateVariables["/f3"].state.extrema.isResolved).eq(false); - - expect(stateVariables["/g"].state.formula.isResolved).eq(true); - expect(stateVariables["/g"].state.symbolicfs.isResolved).eq(false); - expect(stateVariables["/g"].state.numericalfs.isResolved).eq(false); - expect(stateVariables["/g"].state.allMaxima.isResolved).eq(false); - expect(stateVariables["/g"].state.allMinima.isResolved).eq(false); - expect(stateVariables["/g"].state.allExtrema.isResolved).eq(false); - expect(stateVariables["/g"].state.numMaxima.isResolved).eq(false); - expect(stateVariables["/g"].state.numMinima.isResolved).eq(false); - expect(stateVariables["/g"].state.numExtrema.isResolved).eq(false); - expect(stateVariables["/g"].state.maxima.isResolved).eq(false); - expect(stateVariables["/g"].state.minima.isResolved).eq(false); - expect(stateVariables["/g"].state.extrema.isResolved).eq(false); - - expect(stateVariables["/g2"].state.formula.isResolved).eq(true); - expect(stateVariables["/g2"].state.symbolicfs.isResolved).eq(false); - expect(stateVariables["/g2"].state.numericalfs.isResolved).eq( - false, - ); - expect(stateVariables["/g2"].state.allMaxima.isResolved).eq(false); - expect(stateVariables["/g2"].state.allMinima.isResolved).eq(false); - expect(stateVariables["/g2"].state.allExtrema.isResolved).eq(false); - expect(stateVariables["/g2"].state.numMaxima.isResolved).eq(false); - expect(stateVariables["/g2"].state.numMinima.isResolved).eq(false); - expect(stateVariables["/g2"].state.numExtrema.isResolved).eq(false); - expect(stateVariables["/g2"].state.maxima.isResolved).eq(false); - expect(stateVariables["/g2"].state.minima.isResolved).eq(false); - expect(stateVariables["/g2"].state.extrema.isResolved).eq(false); - - expect(stateVariables["/g3"].state.formula.isResolved).eq(true); - expect(stateVariables["/g3"].state.symbolicfs.isResolved).eq(false); - expect(stateVariables["/g3"].state.numericalfs.isResolved).eq( - false, - ); - expect(stateVariables["/g3"].state.allMaxima.isResolved).eq(false); - expect(stateVariables["/g3"].state.allMinima.isResolved).eq(false); - expect(stateVariables["/g3"].state.allExtrema.isResolved).eq(false); - expect(stateVariables["/g3"].state.numMaxima.isResolved).eq(false); - expect(stateVariables["/g3"].state.numMinima.isResolved).eq(false); - expect(stateVariables["/g3"].state.numExtrema.isResolved).eq(false); - expect(stateVariables["/g3"].state.maxima.isResolved).eq(false); - expect(stateVariables["/g3"].state.minima.isResolved).eq(false); - expect(stateVariables["/g3"].state.extrema.isResolved).eq(false); - }); - }); - - it("function determined by formula, specify 1 input", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - 3/(1+e^(-x/2)) - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_function1"].stateValues.numInputs).eq(1); - - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - // let numericalf = (stateVariables['/_function1'].stateValues.numericalfs)[0]; - // let symbolicf = (stateVariables['/_function1'].stateValues.symbolicfs)[0]; - - expect(f(-5)).closeTo(3 / (1 + Math.exp(5 / 2)), 1e-12); - expect(f(1)).closeTo(3 / (1 + Math.exp(-1 / 2)), 1e-12); - // expect(numericalf(-5)).closeTo(3 / (1 + Math.exp(5 / 2)), 1E-12); - // expect(numericalf(1)).closeTo(3 / (1 + Math.exp(-1 / 2)), 1E-12); - // expect(symbolicf(-5).equals(me.fromText('3/(1+e^(5/2))'))).eq(true) - // expect(symbolicf(1).equals(me.fromText('3/(1+e^(-1/2))'))).eq(true) - // expect(symbolicf('z').equals(me.fromText('3/(1+e^(-z/2))'))).eq(true) - }); - }); - - it("function of two variables determined by formula", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 3/(y+e^(-x/2)) -

$_function1.domain

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−∞,∞)"); - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(2) - .should("have.text", "(−∞,∞)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_function1"].stateValues.numInputs).eq(2); - expect(stateVariables["/_function1"].stateValues.domain).eqls([ - [ - "interval", - ["tuple", -Infinity, Infinity], - ["tuple", false, false], - ], - [ - "interval", - ["tuple", -Infinity, Infinity], - ["tuple", false, false], - ], - ]); - - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - - expect(f(-5, 7)).closeTo(3 / (7 + Math.exp(5 / 2)), 1e-12); - expect(f(1, 4)).closeTo(3 / (4 + Math.exp(-1 / 2)), 1e-12); - }); - }); - - it("function of two variables determined by formula, specify variables", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 3/(r+e^(-q/2)) -

$_function1.domain

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−∞,∞)"); - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(2) - .should("have.text", "(−∞,∞)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_function1"].stateValues.numInputs).eq(2); - expect(stateVariables["/_function1"].stateValues.domain).eqls([ - [ - "interval", - ["tuple", -Infinity, Infinity], - ["tuple", false, false], - ], - [ - "interval", - ["tuple", -Infinity, Infinity], - ["tuple", false, false], - ], - ]); - - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - - expect(f(-5, 7)).closeTo(3 / (7 + Math.exp(5 / 2)), 1e-12); - expect(f(1, 4)).closeTo(3 / (4 + Math.exp(-1 / 2)), 1e-12); - }); - }); - - it("function of two variables determined by formula, specify variables, no numInputs specified", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 3/(r+e^(-q/2)) -

$_function1.domain

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−∞,∞)"); - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(2) - .should("have.text", "(−∞,∞)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_function1"].stateValues.numInputs).eq(2); - expect(stateVariables["/_function1"].stateValues.domain).eqls([ - [ - "interval", - ["tuple", -Infinity, Infinity], - ["tuple", false, false], - ], - [ - "interval", - ["tuple", -Infinity, Infinity], - ["tuple", false, false], - ], - ]); - - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - - expect(f(-5, 7)).closeTo(3 / (7 + Math.exp(5 / 2)), 1e-12); - expect(f(1, 4)).closeTo(3 / (4 + Math.exp(-1 / 2)), 1e-12); - }); - }); - - it("function of two variables determined by formula, specify variables, no numInputs specified, restrict domain", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 3/(r+e^(-q/2)) -

$_function1.domain

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−4,2]"); - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(2) - .should("have.text", "[1,3)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_function1"].stateValues.numInputs).eq(2); - expect(stateVariables["/_function1"].stateValues.domain).eqls([ - ["interval", ["tuple", -4, 2], ["tuple", false, true]], - ["interval", ["tuple", 1, 3], ["tuple", true, false]], - ]); - - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - - expect(f(-4, 2)).eqls(NaN); - expect(f(3, 3)).eqls(NaN); - expect(f(2, 1)).closeTo(3 / (1 + Math.exp(-1)), 1e-12); - expect(f(-3, 2)).closeTo(3 / (2 + Math.exp(3 / 2)), 1e-12); - }); - }); - - it("function of three variables determined by formula", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - z/(y+e^(-x/2)) -

$_function1.domain

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−∞,∞)"); - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(2) - .should("have.text", "(−∞,∞)"); - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(4) - .should("have.text", "(−∞,∞)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_function1"].stateValues.numInputs).eq(3); - expect(stateVariables["/_function1"].stateValues.domain).eqls([ - [ - "interval", - ["tuple", -Infinity, Infinity], - ["tuple", false, false], - ], - [ - "interval", - ["tuple", -Infinity, Infinity], - ["tuple", false, false], - ], - [ - "interval", - ["tuple", -Infinity, Infinity], - ["tuple", false, false], - ], - ]); - - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - - expect(f(-5, 7, -2)).closeTo(-2 / (7 + Math.exp(5 / 2)), 1e-12); - expect(f(1, 4, -9)).closeTo(-9 / (4 + Math.exp(-1 / 2)), 1e-12); - }); - }); - - it("function of three variables determined by formula, specify variables", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - s/(r+e^(-q/2)) -

$_function1.domain

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−∞,∞)"); - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(2) - .should("have.text", "(−∞,∞)"); - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(4) - .should("have.text", "(−∞,∞)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_function1"].stateValues.numInputs).eq(3); - expect(stateVariables["/_function1"].stateValues.domain).eqls([ - [ - "interval", - ["tuple", -Infinity, Infinity], - ["tuple", false, false], - ], - [ - "interval", - ["tuple", -Infinity, Infinity], - ["tuple", false, false], - ], - [ - "interval", - ["tuple", -Infinity, Infinity], - ["tuple", false, false], - ], - ]); - - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - - expect(f(-5, 7, -2)).closeTo(-2 / (7 + Math.exp(5 / 2)), 1e-12); - expect(f(1, 4, -9)).closeTo(-9 / (4 + Math.exp(-1 / 2)), 1e-12); - }); - }); - - it("function of three variables determined by formula, specify variables, restrict domain", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - s/(r+e^(-q/2)) -

$_function1.domain

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(2,5)"); - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(2) - .should("have.text", "[−4,4]"); - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(4) - .should("have.text", "[−3,−1)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_function1"].stateValues.numInputs).eq(3); - expect(stateVariables["/_function1"].stateValues.domain).eqls([ - ["interval", ["tuple", 2, 5], ["tuple", false, false]], - ["interval", ["tuple", -4, 4], ["tuple", true, true]], - ["interval", ["tuple", -3, -1], ["tuple", true, false]], - ]); - - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - - expect(f(5, 3, -3)).eqls(NaN); - expect(f(4, 3, -3)).closeTo(-3 / (3 + Math.exp(-2)), 1e-12); - expect(f(3, 2, -1)).eqls(NaN); - expect(f(3, 2, -2)).closeTo(-2 / (2 + Math.exp(-3 / 2)), 1e-12); - }); - }); - - it("function of four variables determined by formula", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - x_3/(x_2+e^(-x_1/2))+x_4 -

$_function1.domain

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−∞,∞)"); - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(2) - .should("have.text", "(−∞,∞)"); - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(4) - .should("have.text", "(−∞,∞)"); - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(6) - .should("have.text", "(−∞,∞)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_function1"].stateValues.numInputs).eq(4); - expect(stateVariables["/_function1"].stateValues.domain).eqls([ - [ - "interval", - ["tuple", -Infinity, Infinity], - ["tuple", false, false], - ], - [ - "interval", - ["tuple", -Infinity, Infinity], - ["tuple", false, false], - ], - [ - "interval", - ["tuple", -Infinity, Infinity], - ["tuple", false, false], - ], - [ - "interval", - ["tuple", -Infinity, Infinity], - ["tuple", false, false], - ], - ]); - - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - - expect(f(-5, 7, -2, 6)).closeTo( - -2 / (7 + Math.exp(5 / 2)) + 6, - 1e-12, - ); - expect(f(1, 4, -9, -8)).closeTo( - -9 / (4 + Math.exp(-1 / 2)) - 8, - 1e-12, - ); - }); - }); - - it("function of four variables determined by formula, specify some variables", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - z/(y+e^(-x/2))+x_4 -

$_function1.domain

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−∞,∞)"); - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(2) - .should("have.text", "(−∞,∞)"); - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(4) - .should("have.text", "(−∞,∞)"); - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(6) - .should("have.text", "(−∞,∞)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_function1"].stateValues.numInputs).eq(4); - expect(stateVariables["/_function1"].stateValues.domain).eqls([ - [ - "interval", - ["tuple", -Infinity, Infinity], - ["tuple", false, false], - ], - [ - "interval", - ["tuple", -Infinity, Infinity], - ["tuple", false, false], - ], - [ - "interval", - ["tuple", -Infinity, Infinity], - ["tuple", false, false], - ], - [ - "interval", - ["tuple", -Infinity, Infinity], - ["tuple", false, false], - ], - ]); - - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - - expect(f(-5, 7, -2, 6)).closeTo( - -2 / (7 + Math.exp(5 / 2)) + 6, - 1e-12, - ); - expect(f(1, 4, -9, -8)).closeTo( - -9 / (4 + Math.exp(-1 / 2)) - 8, - 1e-12, - ); - }); - }); - - it("function of four variables determined by formula, specify some variables, restrict domain", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - z/(y+e^(-x/2))+x_4 -

$_function1.domain

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "[−5,1]"); - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(2) - .should("have.text", "[2,4)"); - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(4) - .should("have.text", "(4,7]"); - cy.get(cesc("#\\/_p1") + " .mjx-mrow") - .eq(6) - .should("have.text", "(−8,−4)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_function1"].stateValues.numInputs).eq(4); - expect(stateVariables["/_function1"].stateValues.domain).eqls([ - ["interval", ["tuple", -5, 1], ["tuple", true, true]], - ["interval", ["tuple", 2, 4], ["tuple", true, false]], - ["interval", ["tuple", 4, 7], ["tuple", false, true]], - ["interval", ["tuple", -8, -4], ["tuple", false, false]], - ]); - - let f = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - - expect(f(-5, 2, 7, -4)).eqls(NaN); - expect(f(-5, 2, 7, -5)).closeTo( - 7 / (2 + Math.exp(5 / 2)) - 5, - 1e-12, - ); - }); - }); - - it("2D vector-valued function of a single variable", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - (x^2, x^3) - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_function1"].stateValues.numInputs).eq(1); - expect(stateVariables["/_function1"].stateValues.numOutputs).eq(2); - - // let f1 = (stateVariables['/_function1'].stateValues.fs)[0]; - let f1 = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - let f2 = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[1], - ); - // let numericalf1 = (stateVariables['/_function1'].stateValues.numericalfs)[0]; - // let numericalf2 = (stateVariables['/_function1'].stateValues.numericalfs)[1]; - // let symbolicf1 = (stateVariables['/_function1'].stateValues.symbolicfs)[0]; - // let symbolicf2 = (stateVariables['/_function1'].stateValues.symbolicfs)[1]; - - expect(f1(-5)).closeTo(25, 1e-12); - expect(f2(-5)).closeTo(-125, 1e-12); - expect(f1(3)).closeTo(9, 1e-12); - expect(f2(3)).closeTo(27, 1e-12); - // expect(numericalf1(-5)).closeTo(25, 1E-12); - // expect(numericalf2(-5)).closeTo(-125, 1E-12); - // expect(numericalf1(3)).closeTo(9, 1E-12); - // expect(numericalf2(3)).closeTo(27, 1E-12); - // expect(symbolicf1(-5).equals(me.fromText('(-5)^2'))).eq(true); - // expect(symbolicf2(-5).equals(me.fromText('(-5)^3'))).eq(true); - // expect(symbolicf1(3).equals(me.fromText('3^2'))).eq(true); - // expect(symbolicf2(3).equals(me.fromText('3^3'))).eq(true); - // expect(symbolicf1('z').equals(me.fromText('z^2'))).eq(true); - // expect(symbolicf2('z').equals(me.fromText('z^3'))).eq(true); - }); - }); - - it("2D vector-valued function of a single variable, specify variable", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - (t^2, t^3) - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_function1"].stateValues.numInputs).eq(1); - expect(stateVariables["/_function1"].stateValues.numOutputs).eq(2); - - let f1 = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - let f2 = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[1], - ); - - let numericalf1 = - stateVariables["/_function1"].stateValues.numericalfs[0]; - let numericalf2 = - stateVariables["/_function1"].stateValues.numericalfs[1]; - let symbolicf1 = - stateVariables["/_function1"].stateValues.symbolicfs[0]; - // let symbolicf2 = (stateVariables['/_function1'].stateValues.symbolicfs)[1]; - - expect(f1(-5)).closeTo(25, 1e-12); - expect(f2(-5)).closeTo(-125, 1e-12); - expect(f1(3)).closeTo(9, 1e-12); - expect(f2(3)).closeTo(27, 1e-12); - // expect(numericalf1(-5)).closeTo(25, 1E-12); - // expect(numericalf2(-5)).closeTo(-125, 1E-12); - // expect(numericalf1(3)).closeTo(9, 1E-12); - // expect(numericalf2(3)).closeTo(27, 1E-12); - // expect(symbolicf1(-5).equals(me.fromText('(-5)^2'))).eq(true); - // expect(symbolicf2(-5).equals(me.fromText('(-5)^3'))).eq(true); - // expect(symbolicf1(3).equals(me.fromText('3^2'))).eq(true); - // expect(symbolicf2(3).equals(me.fromText('3^3'))).eq(true); - // expect(symbolicf1('z').equals(me.fromText('z^2'))).eq(true); - // expect(symbolicf2('z').equals(me.fromText('z^3'))).eq(true); - }); - }); - - it("2D vector-valued function of a single variable, specify numOutputs", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - (t^2, t^3) - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_function1"].stateValues.numInputs).eq(1); - expect(stateVariables["/_function1"].stateValues.numOutputs).eq(2); - - let f1 = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - let f2 = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[1], - ); - // let numericalf1 = (stateVariables['/_function1'].stateValues.numericalfs)[0]; - // let numericalf2 = (stateVariables['/_function1'].stateValues.numericalfs)[1]; - // let symbolicf1 = (stateVariables['/_function1'].stateValues.symbolicfs)[0]; - // let symbolicf2 = (stateVariables['/_function1'].stateValues.symbolicfs)[1]; - - expect(f1(-5)).closeTo(25, 1e-12); - expect(f2(-5)).closeTo(-125, 1e-12); - expect(f1(3)).closeTo(9, 1e-12); - expect(f2(3)).closeTo(27, 1e-12); - // expect(numericalf1(-5)).closeTo(25, 1E-12); - // expect(numericalf2(-5)).closeTo(-125, 1E-12); - // expect(numericalf1(3)).closeTo(9, 1E-12); - // expect(numericalf2(3)).closeTo(27, 1E-12); - // expect(symbolicf1(-5).equals(me.fromText('(-5)^2'))).eq(true); - // expect(symbolicf2(-5).equals(me.fromText('(-5)^3'))).eq(true); - // expect(symbolicf1(3).equals(me.fromText('3^2'))).eq(true); - // expect(symbolicf2(3).equals(me.fromText('3^3'))).eq(true); - // expect(symbolicf1('z').equals(me.fromText('z^2'))).eq(true); - // expect(symbolicf2('z').equals(me.fromText('z^3'))).eq(true); - }); - }); - - it("3D vector-valued function of a single variable", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - (x^2, x^3, x^4) - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_function1"].stateValues.numInputs).eq(1); - expect(stateVariables["/_function1"].stateValues.numOutputs).eq(3); - - let f1 = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - let f2 = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[1], - ); - let f3 = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[2], - ); - // let numericalf1 = (stateVariables['/_function1'].stateValues.numericalfs)[0]; - // let numericalf2 = (stateVariables['/_function1'].stateValues.numericalfs)[1]; - // let numericalf3 = (stateVariables['/_function1'].stateValues.numericalfs)[2]; - // let symbolicf1 = (stateVariables['/_function1'].stateValues.symbolicfs)[0]; - // let symbolicf2 = (stateVariables['/_function1'].stateValues.symbolicfs)[1]; - // let symbolicf3 = (stateVariables['/_function1'].stateValues.symbolicfs)[2]; - - expect(f1(-5)).closeTo(25, 1e-12); - expect(f2(-5)).closeTo(-125, 1e-12); - expect(f3(-5)).closeTo(625, 1e-12); - expect(f1(3)).closeTo(9, 1e-12); - expect(f2(3)).closeTo(27, 1e-12); - expect(f3(3)).closeTo(81, 1e-12); - // expect(numericalf1(-5)).closeTo(25, 1E-12); - // expect(numericalf2(-5)).closeTo(-125, 1E-12); - // expect(numericalf3(-5)).closeTo(625, 1E-12); - // expect(numericalf1(3)).closeTo(9, 1E-12); - // expect(numericalf2(3)).closeTo(27, 1E-12); - // expect(numericalf3(3)).closeTo(81, 1E-12); - // expect(symbolicf1(-5).equals(me.fromText('(-5)^2'))).eq(true); - // expect(symbolicf2(-5).equals(me.fromText('(-5)^3'))).eq(true); - // expect(symbolicf3(-5).equals(me.fromText('(-5)^4'))).eq(true); - // expect(symbolicf1(3).equals(me.fromText('3^2'))).eq(true); - // expect(symbolicf2(3).equals(me.fromText('3^3'))).eq(true); - // expect(symbolicf3(3).equals(me.fromText('3^4'))).eq(true); - // expect(symbolicf1('z').equals(me.fromText('z^2'))).eq(true); - // expect(symbolicf2('z').equals(me.fromText('z^3'))).eq(true); - // expect(symbolicf3('z').equals(me.fromText('z^4'))).eq(true); - }); - }); - - it("3D vector-valued function of a single variable, specify variable", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - (t^2, t^3, t^4) - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_function1"].stateValues.numInputs).eq(1); - expect(stateVariables["/_function1"].stateValues.numOutputs).eq(3); - - let f1 = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - let f2 = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[1], - ); - let f3 = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[2], - ); - // let numericalf1 = (stateVariables['/_function1'].stateValues.numericalfs)[0]; - // let numericalf2 = (stateVariables['/_function1'].stateValues.numericalfs)[1]; - // let numericalf3 = (stateVariables['/_function1'].stateValues.numericalfs)[2]; - // let symbolicf1 = (stateVariables['/_function1'].stateValues.symbolicfs)[0]; - // let symbolicf2 = (stateVariables['/_function1'].stateValues.symbolicfs)[1]; - // let symbolicf3 = (stateVariables['/_function1'].stateValues.symbolicfs)[2]; - - expect(f1(-5)).closeTo(25, 1e-12); - expect(f2(-5)).closeTo(-125, 1e-12); - expect(f3(-5)).closeTo(625, 1e-12); - expect(f1(3)).closeTo(9, 1e-12); - expect(f2(3)).closeTo(27, 1e-12); - expect(f3(3)).closeTo(81, 1e-12); - // expect(numericalf1(-5)).closeTo(25, 1E-12); - // expect(numericalf2(-5)).closeTo(-125, 1E-12); - // expect(numericalf3(-5)).closeTo(625, 1E-12); - // expect(numericalf1(3)).closeTo(9, 1E-12); - // expect(numericalf2(3)).closeTo(27, 1E-12); - // expect(numericalf3(3)).closeTo(81, 1E-12); - // expect(symbolicf1(-5).equals(me.fromText('(-5)^2'))).eq(true); - // expect(symbolicf2(-5).equals(me.fromText('(-5)^3'))).eq(true); - // expect(symbolicf3(-5).equals(me.fromText('(-5)^4'))).eq(true); - // expect(symbolicf1(3).equals(me.fromText('3^2'))).eq(true); - // expect(symbolicf2(3).equals(me.fromText('3^3'))).eq(true); - // expect(symbolicf3(3).equals(me.fromText('3^4'))).eq(true); - // expect(symbolicf1('z').equals(me.fromText('z^2'))).eq(true); - // expect(symbolicf2('z').equals(me.fromText('z^3'))).eq(true); - // expect(symbolicf3('z').equals(me.fromText('z^4'))).eq(true); - }); - }); - - it("2D vector-valued function of two variables", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - (x^2y^3, x^3y^2) - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_function1"].stateValues.numInputs).eq(2); - expect(stateVariables["/_function1"].stateValues.numOutputs).eq(2); - - let f1 = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - let f2 = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[1], - ); - // let numericalf1 = (stateVariables['/_function1'].stateValues.numericalfs)[0]; - // let numericalf2 = (stateVariables['/_function1'].stateValues.numericalfs)[1]; - // let symbolicf1 = (stateVariables['/_function1'].stateValues.symbolicfs)[0]; - // let symbolicf2 = (stateVariables['/_function1'].stateValues.symbolicfs)[1]; - - expect(f1(-5, 2)).closeTo(200, 1e-12); - expect(f2(-5, 2)).closeTo(-500, 1e-12); - expect(f1(3, -4)).closeTo(-576, 1e-12); - expect(f2(3, -4)).closeTo(432, 1e-12); - // expect(numericalf1(-5, 2)).closeTo(200, 1E-12); - // expect(numericalf2(-5, 2)).closeTo(-500, 1E-12); - // expect(numericalf1(3, -4)).closeTo(-576, 1E-12); - // expect(numericalf2(3, -4)).closeTo(432, 1E-12); - // expect(symbolicf1(-5, 2).equals(me.fromText('(-5)^2*2^3'))).eq(true); - // expect(symbolicf2(-5, 2).equals(me.fromText('(-5)^3*2^2'))).eq(true); - // expect(symbolicf1(3, -4).equals(me.fromText('3^2*(-4)^3'))).eq(true); - // expect(symbolicf2(3, -4).equals(me.fromText('3^3*(-4)^2'))).eq(true); - // expect(symbolicf1('z', 'w').equals(me.fromText('z^2w^3'))).eq(true); - // expect(symbolicf2('z', 'w').equals(me.fromText('z^3w^2'))).eq(true); - }); - }); - - it("3D vector-valued function of two variables", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - (s^2t^3, s^3t^2, st) - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_function1"].stateValues.numInputs).eq(2); - expect(stateVariables["/_function1"].stateValues.numOutputs).eq(3); - - let f1 = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - let f2 = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[1], - ); - let f3 = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[2], - ); - // let numericalf1 = (stateVariables['/_function1'].stateValues.numericalfs)[0]; - // let numericalf2 = (stateVariables['/_function1'].stateValues.numericalfs)[1]; - // let numericalf3 = (stateVariables['/_function1'].stateValues.numericalfs)[2]; - // let symbolicf1 = (stateVariables['/_function1'].stateValues.symbolicfs)[0]; - // let symbolicf2 = (stateVariables['/_function1'].stateValues.symbolicfs)[1]; - // let symbolicf3 = (stateVariables['/_function1'].stateValues.symbolicfs)[2]; - - expect(f1(-5, 2)).closeTo(200, 1e-12); - expect(f2(-5, 2)).closeTo(-500, 1e-12); - expect(f3(-5, 2)).closeTo(-10, 1e-12); - expect(f1(3, -4)).closeTo(-576, 1e-12); - expect(f2(3, -4)).closeTo(432, 1e-12); - expect(f3(3, -4)).closeTo(-12, 1e-12); - // expect(numericalf1(-5, 2)).closeTo(200, 1E-12); - // expect(numericalf2(-5, 2)).closeTo(-500, 1E-12); - // expect(numericalf3(-5, 2)).closeTo(-10, 1E-12); - // expect(numericalf1(3, -4)).closeTo(-576, 1E-12); - // expect(numericalf2(3, -4)).closeTo(432, 1E-12); - // expect(numericalf3(3, -4)).closeTo(-12, 1E-12); - // expect(symbolicf1(-5, 2).equals(me.fromText('(-5)^2*2^3'))).eq(true); - // expect(symbolicf2(-5, 2).equals(me.fromText('(-5)^3*2^2'))).eq(true); - // expect(symbolicf3(-5, 2).equals(me.fromText('(-5)*2'))).eq(true); - // expect(symbolicf1(3, -4).equals(me.fromText('3^2*(-4)^3'))).eq(true); - // expect(symbolicf2(3, -4).equals(me.fromText('3^3*(-4)^2'))).eq(true); - // expect(symbolicf3(3, -4).equals(me.fromText('3*(-4)'))).eq(true); - // expect(symbolicf1('z', 'w').equals(me.fromText('z^2w^3'))).eq(true); - // expect(symbolicf2('z', 'w').equals(me.fromText('z^3w^2'))).eq(true); - // expect(symbolicf3('z', 'w').equals(me.fromText('zw'))).eq(true); - }); - }); - - it("3D vector-valued function of two variables, as alt vector", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - ⟨s^2t^3, s^3t^2, st⟩ - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_function1"].stateValues.numInputs).eq(2); - expect(stateVariables["/_function1"].stateValues.numOutputs).eq(3); - - let f1 = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[0], - ); - let f2 = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[1], - ); - let f3 = createFunctionFromDefinition( - stateVariables["/_function1"].stateValues.fDefinitions[2], - ); - // let numericalf1 = (stateVariables['/_function1'].stateValues.numericalfs)[0]; - // let numericalf2 = (stateVariables['/_function1'].stateValues.numericalfs)[1]; - // let numericalf3 = (stateVariables['/_function1'].stateValues.numericalfs)[2]; - // let symbolicf1 = (stateVariables['/_function1'].stateValues.symbolicfs)[0]; - // let symbolicf2 = (stateVariables['/_function1'].stateValues.symbolicfs)[1]; - // let symbolicf3 = (stateVariables['/_function1'].stateValues.symbolicfs)[2]; - - expect(f1(-5, 2)).closeTo(200, 1e-12); - expect(f2(-5, 2)).closeTo(-500, 1e-12); - expect(f3(-5, 2)).closeTo(-10, 1e-12); - expect(f1(3, -4)).closeTo(-576, 1e-12); - expect(f2(3, -4)).closeTo(432, 1e-12); - expect(f3(3, -4)).closeTo(-12, 1e-12); - // expect(numericalf1(-5, 2)).closeTo(200, 1E-12); - // expect(numericalf2(-5, 2)).closeTo(-500, 1E-12); - // expect(numericalf3(-5, 2)).closeTo(-10, 1E-12); - // expect(numericalf1(3, -4)).closeTo(-576, 1E-12); - // expect(numericalf2(3, -4)).closeTo(432, 1E-12); - // expect(numericalf3(3, -4)).closeTo(-12, 1E-12); - // expect(symbolicf1(-5, 2).equals(me.fromText('(-5)^2*2^3'))).eq(true); - // expect(symbolicf2(-5, 2).equals(me.fromText('(-5)^3*2^2'))).eq(true); - // expect(symbolicf3(-5, 2).equals(me.fromText('(-5)*2'))).eq(true); - // expect(symbolicf1(3, -4).equals(me.fromText('3^2*(-4)^3'))).eq(true); - // expect(symbolicf2(3, -4).equals(me.fromText('3^3*(-4)^2'))).eq(true); - // expect(symbolicf3(3, -4).equals(me.fromText('3*(-4)'))).eq(true); - // expect(symbolicf1('z', 'w').equals(me.fromText('z^2w^3'))).eq(true); - // expect(symbolicf2('z', 'w').equals(me.fromText('z^3w^2'))).eq(true); - // expect(symbolicf3('z', 'w').equals(me.fromText('zw'))).eq(true); - }); - }); - - it("copy function and overwrite symbolic attribute", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x^2 - - - x^2 - - - - `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/f1"].stateValues.symbolic).eq(false); - expect(stateVariables["/f2"].stateValues.symbolic).eq(true); - expect(stateVariables["/f3"].stateValues.symbolic).eq(false); - expect(stateVariables["/g1"].stateValues.symbolic).eq(true); - expect(stateVariables["/g2"].stateValues.symbolic).eq(false); - expect(stateVariables["/g3"].stateValues.symbolic).eq(true); - }); - }); - - it("warnings on bad domain", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - x - x - x - x - x - -

f1 domain:

-

f2 domain:

-

f3 domain:

-

f4 domain:

-

f5 domain:

- - x+y - x+y - x+y - x+y - x+y - -

g1 domain: $g1.domain

-

g2 domain: $g2.domain

-

g3 domain: $g3.domain

-

g4 domain: $g4.domain

-

g5 domain: $g5.domain

- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/domainf1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,4)"); - cy.get(cesc2("#/domainf2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−∞,∞)"); - cy.get(cesc2("#/domainf3") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−∞,∞)"); - cy.get(cesc2("#/domainf4") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−∞,∞)"); - cy.get(cesc2("#/domainf5") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,4)"); - - cy.get(cesc2("#/pDomaing1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−∞,∞)"); - cy.get(cesc2("#/pDomaing1") + " .mjx-mrow") - .eq(2) - .should("have.text", "(−∞,∞)"); - cy.get(cesc2("#/pDomaing2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,4)"); - cy.get(cesc2("#/pDomaing2") + " .mjx-mrow") - .eq(2) - .should("have.text", "(5,6)"); - cy.get(cesc2("#/pDomaing3") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−∞,∞)"); - cy.get(cesc2("#/pDomaing3") + " .mjx-mrow") - .eq(2) - .should("have.text", "(−∞,∞)"); - cy.get(cesc2("#/pDomaing4") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−∞,∞)"); - cy.get(cesc2("#/pDomaing4") + " .mjx-mrow") - .eq(2) - .should("have.text", "(−∞,∞)"); - cy.get(cesc2("#/pDomaing5") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,4)"); - cy.get(cesc2("#/pDomaing5") + " .mjx-mrow") - .eq(2) - .should("have.text", "(5,6)"); - - cy.window().then(async (win) => { - let errorWarnings = await win.returnErrorWarnings1(); - - expect(errorWarnings.errors.length).eq(0); - expect(errorWarnings.warnings.length).eq(7); - - expect(errorWarnings.warnings[0].message).contain( - `Insufficient dimensions for domain for function. Domain has 0 intervals but the function has 1 input.`, - ); - expect(errorWarnings.warnings[0].level).eq(1); - expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(3); - expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(5); - expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(3); - expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(47); - - expect(errorWarnings.warnings[1].message).contain( - `Invalid format for domain for function`, - ); - expect(errorWarnings.warnings[1].level).eq(1); - expect(errorWarnings.warnings[1].doenetMLrange.lineBegin).eq(4); - expect(errorWarnings.warnings[1].doenetMLrange.charBegin).eq(5); - expect(errorWarnings.warnings[1].doenetMLrange.lineEnd).eq(4); - expect(errorWarnings.warnings[1].doenetMLrange.charEnd).eq(53); - - expect(errorWarnings.warnings[2].message).contain( - `Insufficient dimensions for domain for function. Domain has 0 intervals but the function has 1 input.`, - ); - expect(errorWarnings.warnings[2].level).eq(1); - expect(errorWarnings.warnings[2].doenetMLrange.lineBegin).eq(5); - expect(errorWarnings.warnings[2].doenetMLrange.charBegin).eq(5); - expect(errorWarnings.warnings[2].doenetMLrange.lineEnd).eq(5); - expect(errorWarnings.warnings[2].doenetMLrange.charEnd).eq(46); - - expect(errorWarnings.warnings[3].message).contain( - `Insufficient dimensions for domain for function. Domain has 1 interval but the function has 2 inputs.`, - ); - expect(errorWarnings.warnings[3].level).eq(1); - expect(errorWarnings.warnings[3].doenetMLrange.lineBegin).eq(14); - expect(errorWarnings.warnings[3].doenetMLrange.charBegin).eq(5); - expect(errorWarnings.warnings[3].doenetMLrange.lineEnd).eq(14); - expect(errorWarnings.warnings[3].doenetMLrange.charEnd).eq(67); - - expect(errorWarnings.warnings[4].message).contain( - `Invalid format for domain for function`, - ); - expect(errorWarnings.warnings[4].level).eq(1); - expect(errorWarnings.warnings[4].doenetMLrange.lineBegin).eq(16); - expect(errorWarnings.warnings[4].doenetMLrange.charBegin).eq(5); - expect(errorWarnings.warnings[4].doenetMLrange.lineEnd).eq(16); - expect(errorWarnings.warnings[4].doenetMLrange.charEnd).eq(75); - - expect(errorWarnings.warnings[5].message).contain( - `Insufficient dimensions for domain for function. Domain has 0 intervals but the function has 2 inputs.`, - ); - expect(errorWarnings.warnings[5].level).eq(1); - expect(errorWarnings.warnings[5].doenetMLrange.lineBegin).eq(17); - expect(errorWarnings.warnings[5].doenetMLrange.charBegin).eq(5); - expect(errorWarnings.warnings[5].doenetMLrange.lineEnd).eq(17); - expect(errorWarnings.warnings[5].doenetMLrange.charEnd).eq(62); - - expect(errorWarnings.warnings[6].message).contain( - `Invalid format for attribute domain of `, - ); - expect(errorWarnings.warnings[6].level).eq(1); - expect(errorWarnings.warnings[6].doenetMLrange.lineBegin).eq(3); - expect(errorWarnings.warnings[6].doenetMLrange.charBegin).eq(33); - expect(errorWarnings.warnings[6].doenetMLrange.lineEnd).eq(3); - expect(errorWarnings.warnings[6].doenetMLrange.charEnd).eq(33); - }); - }); - - it("copy function and overwrite numInputs", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - xyz - - - -

$$f1(a)

-

$$f2(a,b)

-

$$f3(a,b,c)

- `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/p1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("ayz"); - }); - cy.get(cesc("#\\/p2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("abz"); - }); - cy.get(cesc("#\\/p3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("abc"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/f1"].stateValues.numInputs).eq(1); - expect(stateVariables["/f2"].stateValues.numInputs).eq(2); - expect(stateVariables["/f3"].stateValues.numInputs).eq(3); - expect( - stateVariables["/f1"].stateValues.variables.map((x) => x), - ).eqls(["x"]); - expect( - stateVariables["/f2"].stateValues.variables.map((x) => x), - ).eqls(["x", "y"]); - expect( - stateVariables["/f3"].stateValues.variables.map((x) => x), - ).eqls(["x", "y", "z"]); - }); - }); - - it("copy function and overwrite variables", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - xyz - - - - - - -

$$f1(a)

-

$$f2(a,b)

-

$$f3(a,b,c)

-

$$f4(a,b)

-

$$f5(a)

-

$$f5a(a)

- `, - }, - "*", - ); - }); - - //wait for window to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.get(cesc("#\\/p1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("ayz"); - }); - cy.get(cesc("#\\/p2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("abz"); - }); - cy.get(cesc("#\\/p3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("abc"); - }); - cy.get(cesc("#\\/p4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("xba"); - }); - cy.get(cesc("#\\/p5") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("xaz"); - }); - cy.get(cesc("#\\/p5a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("xaz"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/f1"].stateValues.numInputs).eq(1); - expect(stateVariables["/f2"].stateValues.numInputs).eq(2); - expect(stateVariables["/f3"].stateValues.numInputs).eq(3); - expect(stateVariables["/f4"].stateValues.numInputs).eq(2); - expect(stateVariables["/f5"].stateValues.numInputs).eq(1); - expect(stateVariables["/f5a"].stateValues.numInputs).eq(1); - expect( - stateVariables["/f1"].stateValues.variables.map((x) => x), - ).eqls(["x"]); - expect( - stateVariables["/f2"].stateValues.variables.map((x) => x), - ).eqls(["x", "y"]); - expect( - stateVariables["/f3"].stateValues.variables.map((x) => x), - ).eqls(["x", "y", "z"]); - expect( - stateVariables["/f4"].stateValues.variables.map((x) => x), - ).eqls(["z", "y"]); - expect( - stateVariables["/f5"].stateValues.variables.map((x) => x), - ).eqls(["y"]); - expect( - stateVariables["/f5a"].stateValues.variables.map((x) => x), - ).eqls(["y"]); - }); - }); - - it("copy props with propIndex", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

n:

- - - - - -

-

-

- -

-

-

- -

-

-

- -

-

-

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/mn1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(2,1)"); - }); - cy.get(cesc("#\\/mx1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(8,9)"); - }); - cy.get(cesc("#\\/ex1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(−4,4)"); - }); - cy.get(cesc("#\\/mnl1")).should("have.text", "2"); - cy.get(cesc("#\\/mxl1")).should("have.text", "8"); - cy.get(cesc("#\\/exl1")).should("have.text", "-4"); - - cy.get(cesc("#\\/mnv1")).should("have.text", "1"); - cy.get(cesc("#\\/mxv1")).should("have.text", "9"); - cy.get(cesc("#\\/exv1")).should("have.text", "4"); - - cy.get(cesc("#\\/mn11")).should("have.text", "-5"); - cy.get(cesc("#\\/mx11")).should("have.text", "4"); - cy.get(cesc("#\\/ex11")).should("have.text", "-5"); - - cy.log("set propIndex to 1"); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}1{enter}", { - force: true, - }); - - cy.get(cesc("#\\/mnl1")).should("have.text", "-7"); - cy.get(cesc("#\\/mxl1")).should("have.text", "-4"); - cy.get(cesc("#\\/exl1")).should("have.text", "-7"); - - cy.get(cesc("#\\/mnv1")).should("have.text", "-5"); - cy.get(cesc("#\\/mxv1")).should("have.text", "4"); - cy.get(cesc("#\\/exv1")).should("have.text", "-5"); - - cy.get(cesc("#\\/mn11")).should("have.text", "-7"); - cy.get(cesc("#\\/mx11")).should("have.text", "-4"); - cy.get(cesc("#\\/ex11")).should("have.text", "-7"); - - cy.get(cesc("#\\/mn1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(−7,−5)"); - }); - cy.get(cesc("#\\/mx1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(−4,4)"); - }); - cy.get(cesc("#\\/ex1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(−7,−5)"); - }); - }); - - it("copy props with propIndex, dot and array notation", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

n:

- - - - - -

-

-

- -

-

-

- -

-

-

- -

-

-

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/mn1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(2,1)"); - }); - cy.get(cesc("#\\/mx1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(8,9)"); - }); - cy.get(cesc("#\\/ex1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(−4,4)"); - }); - cy.get(cesc("#\\/mnl1")).should("have.text", "2"); - cy.get(cesc("#\\/mxl1")).should("have.text", "8"); - cy.get(cesc("#\\/exl1")).should("have.text", "-4"); - - cy.get(cesc("#\\/mnv1")).should("have.text", "1"); - cy.get(cesc("#\\/mxv1")).should("have.text", "9"); - cy.get(cesc("#\\/exv1")).should("have.text", "4"); - - cy.get(cesc("#\\/mn11")).should("have.text", "-5"); - cy.get(cesc("#\\/mx11")).should("have.text", "4"); - cy.get(cesc("#\\/ex11")).should("have.text", "-5"); - - cy.log("set propIndex to 1"); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}1{enter}", { - force: true, - }); - - cy.get(cesc("#\\/mnl1")).should("have.text", "-7"); - cy.get(cesc("#\\/mxl1")).should("have.text", "-4"); - cy.get(cesc("#\\/exl1")).should("have.text", "-7"); - - cy.get(cesc("#\\/mnv1")).should("have.text", "-5"); - cy.get(cesc("#\\/mxv1")).should("have.text", "4"); - cy.get(cesc("#\\/exv1")).should("have.text", "-5"); - - cy.get(cesc("#\\/mn11")).should("have.text", "-7"); - cy.get(cesc("#\\/mx11")).should("have.text", "-4"); - cy.get(cesc("#\\/ex11")).should("have.text", "-7"); - - cy.get(cesc("#\\/mn1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(−7,−5)"); - }); - cy.get(cesc("#\\/mx1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(−4,4)"); - }); - cy.get(cesc("#\\/ex1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(−7,−5)"); - }); - }); - - it("copy props with multidimensional propIndex, dot and array notation", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

n:

- - - - - -

-

-

- -

-

-

- -

-

-

- -

-

-

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/mn1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(2,1)"); - }); - cy.get(cesc("#\\/mx1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(8,9)"); - }); - cy.get(cesc("#\\/ex1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(−4,4)"); - }); - cy.get(cesc("#\\/mnl1")).should("have.text", "2"); - cy.get(cesc("#\\/mxl1")).should("have.text", "8"); - cy.get(cesc("#\\/exl1")).should("have.text", "-4"); - - cy.get(cesc("#\\/mnv1")).should("have.text", "1"); - cy.get(cesc("#\\/mxv1")).should("have.text", "9"); - cy.get(cesc("#\\/exv1")).should("have.text", "4"); - - cy.get(cesc("#\\/mn11")).should("have.text", "-5"); - cy.get(cesc("#\\/mx11")).should("have.text", "4"); - cy.get(cesc("#\\/ex11")).should("have.text", "-5"); - - cy.log("set propIndex to 1"); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}1{enter}", { - force: true, - }); - - cy.get(cesc("#\\/mnl1")).should("have.text", "-7"); - cy.get(cesc("#\\/mxl1")).should("have.text", "-4"); - cy.get(cesc("#\\/exl1")).should("have.text", "-7"); - - cy.get(cesc("#\\/mnv1")).should("have.text", "-5"); - cy.get(cesc("#\\/mxv1")).should("have.text", "4"); - cy.get(cesc("#\\/exv1")).should("have.text", "-5"); - - cy.get(cesc("#\\/mn11")).should("have.text", "-7"); - cy.get(cesc("#\\/mx11")).should("have.text", "-4"); - cy.get(cesc("#\\/ex11")).should("have.text", "-7"); - - cy.get(cesc("#\\/mn1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(−7,−5)"); - }); - cy.get(cesc("#\\/mx1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(−4,4)"); - }); - cy.get(cesc("#\\/ex1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).eq("(−7,−5)"); - }); - }); - - it("rounding", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - 255.029847 sin(0.52952342x) + 3 - 255.029847 sin(0.52952342x) + 3 - 255.029847 sin(0.52952342x) + 3 - 255.029847 sin(0.52952342x) + 3 - 255.029847 sin(0.52952342x) + 3 - - $f1{name="f1a"} - $f2{name="f2a"} - $f3{name="f3a"} - $f4{name="f4a"} - $f5{name="f5a"} - - $f1.formula{assignNames="f1b"} - $f2.formula{assignNames="f2b"} - $f3.formula{assignNames="f3b"} - $f4.formula{assignNames="f4b"} - $f5.formula{assignNames="f5b"} - - $f1 - $f2 - $f3 - $f4 - $f5 - - $f1.formula - $f2.formula - $f3.formula - $f4.formula - $f5.formula - - $f1a - $f2a - $f3a - $f4a - $f5a - - $f1b - $f2b - $f3b - $f4b - $f5b - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/f1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.53x)+3"); - }); - cy.get(cesc("#\\/f2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255sin(0.5295x)+3"); - }); - cy.get(cesc("#\\/f3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.0sin(0.5295x)+3.000"); - }); - cy.get(cesc("#\\/f4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.53x)+3"); - }); - cy.get(cesc("#\\/f5") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.030sin(0.530x)+3.000"); - }); - - cy.get(cesc("#\\/f1a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.53x)+3"); - }); - cy.get(cesc("#\\/f2a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255sin(0.5295x)+3"); - }); - cy.get(cesc("#\\/f3a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.0sin(0.5295x)+3.000"); - }); - cy.get(cesc("#\\/f4a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.53x)+3"); - }); - cy.get(cesc("#\\/f5a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.030sin(0.530x)+3.000"); - }); - - cy.get(cesc("#\\/f1b") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.53x)+3"); - }); - cy.get(cesc("#\\/f2b") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255sin(0.5295x)+3"); - }); - cy.get(cesc("#\\/f3b") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.0sin(0.5295x)+3.000"); - }); - cy.get(cesc("#\\/f4b") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.53x)+3"); - }); - cy.get(cesc("#\\/f5b") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.030sin(0.530x)+3.000"); - }); - - cy.get(cesc("#\\/f1c") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.53x)+3"); - }); - cy.get(cesc("#\\/f2c") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255sin(0.5295x)+3"); - }); - cy.get(cesc("#\\/f3c") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.0sin(0.5295x)+3.000"); - }); - cy.get(cesc("#\\/f4c") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.53x)+3"); - }); - cy.get(cesc("#\\/f5c") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.030sin(0.530x)+3.000"); - }); - - cy.get(cesc("#\\/f1d") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.53x)+3"); - }); - cy.get(cesc("#\\/f2d") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255sin(0.5295x)+3"); - }); - cy.get(cesc("#\\/f3d") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.0sin(0.5295x)+3.000"); - }); - cy.get(cesc("#\\/f4d") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.53x)+3"); - }); - cy.get(cesc("#\\/f5d") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.030sin(0.530x)+3.000"); - }); - - cy.get(cesc("#\\/f1e") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.53x)+3"); - }); - cy.get(cesc("#\\/f2e") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255sin(0.5295x)+3"); - }); - cy.get(cesc("#\\/f3e") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.0sin(0.5295x)+3.000"); - }); - cy.get(cesc("#\\/f4e") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.53x)+3"); - }); - cy.get(cesc("#\\/f5e") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.030sin(0.530x)+3.000"); - }); - - cy.get(cesc("#\\/f1f") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.53x)+3"); - }); - cy.get(cesc("#\\/f2f") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255sin(0.5295x)+3"); - }); - cy.get(cesc("#\\/f3f") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.0sin(0.5295x)+3.000"); - }); - cy.get(cesc("#\\/f4f") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.53x)+3"); - }); - cy.get(cesc("#\\/f5f") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.030sin(0.530x)+3.000"); - }); - }); - - it("rounding, overwrite on copy", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - 255.029847 sin(0.52952342x) + 3 - 255.029847 sin(0.52952342x) + 3 - 255.029847 sin(0.52952342x) + 3 - 255.029847 sin(0.52952342x) + 3 - 255.029847 sin(0.52952342x) + 3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $f1 - $f2 - $f3 - $f4 - $f5 - $f1 - $f2 - $f3 - $f4 - $f5 - $f1 - $f2 - $f3 - $f4 - $f5 - $f1 - $f2 - $f3 - $f4 - $f5 - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/f1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.53x)+3"); - }); - cy.get(cesc("#\\/f2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255sin(0.5295x)+3"); - }); - cy.get(cesc("#\\/f3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.0sin(0.5295x)+3.000"); - }); - cy.get(cesc("#\\/f4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.53x)+3"); - }); - cy.get(cesc("#\\/f5") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.030sin(0.530x)+3.000"); - }); - - cy.get(cesc("#\\/f1dg6") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.529523x)+3"); - }); - cy.get(cesc("#\\/f2dg6") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.529523x)+3"); - }); - cy.get(cesc("#\\/f3dg6") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.030sin(0.529523x)+3.00000"); - }); - cy.get(cesc("#\\/f4dg6") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.529523x)+3"); - }); - cy.get(cesc("#\\/f5dg6") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.030sin(0.529523x)+3.00000"); - }); - - cy.get(cesc("#\\/f1fdg6") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.529523x)+3"); - }); - cy.get(cesc("#\\/f2fdg6") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.529523x)+3"); - }); - cy.get(cesc("#\\/f3fdg6") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.030sin(0.529523x)+3.00000"); - }); - cy.get(cesc("#\\/f4fdg6") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.529523x)+3"); - }); - cy.get(cesc("#\\/f5fdg6") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.030sin(0.529523x)+3.00000"); - }); - - cy.get(cesc("#\\/f1dg6a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.529523x)+3"); - }); - cy.get(cesc("#\\/f2dg6a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.529523x)+3"); - }); - cy.get(cesc("#\\/f3dg6a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.030sin(0.529523x)+3.00000"); - }); - cy.get(cesc("#\\/f4dg6a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.529523x)+3"); - }); - cy.get(cesc("#\\/f5dg6a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.030sin(0.529523x)+3.00000"); - }); - - cy.get(cesc("#\\/f1dc7") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.029847sin(0.5295234x)+3"); - }); - cy.get(cesc("#\\/f2dc7") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.029847sin(0.5295234x)+3"); - }); - cy.get(cesc("#\\/f3dc7") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.0298470sin(0.5295234x)+3.0000000"); - }); - cy.get(cesc("#\\/f4dc7") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.029847sin(0.5295234x)+3"); - }); - cy.get(cesc("#\\/f5dc7") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.0298470sin(0.5295234x)+3.0000000"); - }); - - cy.get(cesc("#\\/f1fdc7") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.029847sin(0.5295234x)+3"); - }); - cy.get(cesc("#\\/f2fdc7") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.029847sin(0.5295234x)+3"); - }); - cy.get(cesc("#\\/f3fdc7") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.0298470sin(0.5295234x)+3.0000000"); - }); - cy.get(cesc("#\\/f4fdc7") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.029847sin(0.5295234x)+3"); - }); - cy.get(cesc("#\\/f5fdc7") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.0298470sin(0.5295234x)+3.0000000"); - }); - - cy.get(cesc("#\\/f1dc7a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.029847sin(0.5295234x)+3"); - }); - cy.get(cesc("#\\/f2dc7a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.029847sin(0.5295234x)+3"); - }); - cy.get(cesc("#\\/f3dc7a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.0298470sin(0.5295234x)+3.0000000"); - }); - cy.get(cesc("#\\/f4dc7a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.029847sin(0.5295234x)+3"); - }); - cy.get(cesc("#\\/f5dc7a") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.0298470sin(0.5295234x)+3.0000000"); - }); - - cy.get(cesc("#\\/f1pt") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.530x)+3.00"); - }); - cy.get(cesc("#\\/f2pt") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.0sin(0.5295x)+3.000"); - }); - cy.get(cesc("#\\/f3pt") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.0sin(0.5295x)+3.000"); - }); - cy.get(cesc("#\\/f4pt") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.030sin(0.530x)+3.000"); - }); - cy.get(cesc("#\\/f5pt") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.030sin(0.530x)+3.000"); - }); - - cy.get(cesc("#\\/f1fpt") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.530x)+3.00"); - }); - cy.get(cesc("#\\/f2fpt") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.0sin(0.5295x)+3.000"); - }); - cy.get(cesc("#\\/f3fpt") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.0sin(0.5295x)+3.000"); - }); - cy.get(cesc("#\\/f4fpt") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.030sin(0.530x)+3.000"); - }); - cy.get(cesc("#\\/f5fpt") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.030sin(0.530x)+3.000"); - }); - - cy.get(cesc("#\\/f1pta") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.530x)+3.00"); - }); - cy.get(cesc("#\\/f2pta") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.0sin(0.5295x)+3.000"); - }); - cy.get(cesc("#\\/f3pta") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.0sin(0.5295x)+3.000"); - }); - cy.get(cesc("#\\/f4pta") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.030sin(0.530x)+3.000"); - }); - cy.get(cesc("#\\/f5pta") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.030sin(0.530x)+3.000"); - }); - - cy.get(cesc("#\\/f1pf") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.53x)+3"); - }); - cy.get(cesc("#\\/f2pf") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255sin(0.5295x)+3"); - }); - cy.get(cesc("#\\/f3pf") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255sin(0.5295x)+3"); - }); - cy.get(cesc("#\\/f4pf") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.53x)+3"); - }); - cy.get(cesc("#\\/f5pf") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.53x)+3"); - }); - - cy.get(cesc("#\\/f1fpf") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.53x)+3"); - }); - cy.get(cesc("#\\/f2fpf") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255sin(0.5295x)+3"); - }); - cy.get(cesc("#\\/f3fpf") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255sin(0.5295x)+3"); - }); - cy.get(cesc("#\\/f4fpf") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.53x)+3"); - }); - cy.get(cesc("#\\/f5fpf") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.53x)+3"); - }); - - cy.get(cesc("#\\/f1pfa") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.53x)+3"); - }); - cy.get(cesc("#\\/f2pfa") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255sin(0.5295x)+3"); - }); - cy.get(cesc("#\\/f3pfa") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255sin(0.5295x)+3"); - }); - cy.get(cesc("#\\/f4pfa") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.53x)+3"); - }); - cy.get(cesc("#\\/f5pfa") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text).eq("255.03sin(0.53x)+3"); - }); +describe("Function Tag Tests", function () { + beforeEach(() => { + cy.clearIndexedDB(); + cy.visit("/"); }); it("style description changes with theme", () => { @@ -10807,760 +63,4 @@ describe("Function Tag Tests", function () { "C is a thin white function.", ); }); - - it("handle bad through and other defining attributes", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - // page loads - cy.get(cesc2("#/_text1")).should("have.text", "a"); - }); - - it("extrema shadow style number", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - x^3-x - - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/max"].stateValues.styleNumber).eq(2); - expect(stateVariables["/min"].stateValues.styleNumber).eq(2); - expect(stateVariables["/ext1"].stateValues.styleNumber).eq(2); - expect(stateVariables["/ext2"].stateValues.styleNumber).eq(2); - expect(stateVariables["/gmax"].stateValues.styleNumber).eq(2); - expect(stateVariables["/gmin"].stateValues.styleNumber).eq(2); - expect(stateVariables["/sup"].stateValues.styleNumber).eq(2); - expect(stateVariables["/inf"].stateValues.styleNumber).eq(2); - }); - }); - - it("check bugfix: don't get invalid maxima due having incorrect derivative with function of interpolated function", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - $$f(x)-x^4 - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/max1"].stateValues.xs).eqls([1, -1]); - expect(stateVariables["/max2"]).eq(undefined); - expect(stateVariables["/min"]).eq(undefined); - expect(stateVariables["/ext1"].stateValues.xs).eqls([1, -1]); - expect(stateVariables["/ext2"]).eq(undefined); - }); - }); - - it("check bugfix: don't get invalid extrema due to roundoff error with function of interpolated function", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - $$f(x)+(x-3)^2 - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/max"]).eq(undefined); - expect(stateVariables["/min"]).eq(undefined); - expect(stateVariables["/ext"]).eq(undefined); - }); - }); - - it("global extrema, double well, test all properties", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - x^4-8x^2+8 - -

domain:

-

min results for f: $f.globalMinimum{assignNames="fmin"}, $f.globalMinimumLocation{assignNames="fminl"}, $f.globalMinimumValue{assignNames="fminv"}, $f.globalMinimum[1]{assignNames="fminla"}, $f.globalMinimum[2]{assignNames="fminva"}

-

min compactify results for f: $f.globalInfimum{assignNames="fmincd"}, $f.globalInfimumLocation{assignNames="fmincdl"}, $f.globalInfimumValue{assignNames="fmincdv"}, $f.globalInfimum[1]{assignNames="fmincdla"}, $f.globalInfimum[2]{assignNames="fmincdva"}

-

max results for f: $f.globalMaximum{assignNames="fmax"}, $f.globalMaximumLocation{assignNames="fmaxl"}, $f.globalMaximumValue{assignNames="fmaxv"}, $f.globalMaximum[1]{assignNames="fmaxla"}, $f.globalMaximum[2]{assignNames="fmaxva"}

-

max compactify results for f: $f.globalSupremum{assignNames="fmaxcd"}, $f.globalSupremumLocation{assignNames="fmaxcdl"}, $f.globalSupremumValue{assignNames="fmaxcdv"}, $f.globalSupremum[1]{assignNames="fmaxcdla"}, $f.globalSupremum[2]{assignNames="fmaxcdva"}

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/domain") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−∞,∞)"); - - let f100 = 100 ** 4 - 8 * 100 ** 2 + 8; - - cy.get(cesc2("#/fmin") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−2,−8)"); - cy.get(cesc2("#/fminl")).should("have.text", "-2"); - cy.get(cesc2("#/fminla")).should("have.text", "-2"); - cy.get(cesc2("#/fminv")).should("have.text", "-8"); - cy.get(cesc2("#/fminva")).should("have.text", "-8"); - - cy.get(cesc2("#/fmincd") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−2,−8)"); - cy.get(cesc2("#/fmincdl")).should("have.text", "-2"); - cy.get(cesc2("#/fmincdla")).should("have.text", "-2"); - cy.get(cesc2("#/fmincdv")).should("have.text", "-8"); - cy.get(cesc2("#/fmincdva")).should("have.text", "-8"); - - cy.get(cesc2("#/fmax")).should("not.exist"); - cy.get(cesc2("#/fmaxl")).should("have.text", "NaN"); - cy.get(cesc2("#/fmaxla")).should("have.text", "NaN"); - cy.get(cesc2("#/fmaxv")).should("have.text", "NaN"); - cy.get(cesc2("#/fmaxva")).should("have.text", "NaN"); - - cy.get(cesc2("#/fmaxcd") + " .mjx-mrow") - .eq(0) - .should("have.text", `(−100,${nInDOM(f100)})`); - cy.get(cesc2("#/fmaxcdl")).should("have.text", "-100"); - cy.get(cesc2("#/fmaxcdla")).should("have.text", "-100"); - cy.get(cesc2("#/fmaxcdv")).should("have.text", f100.toString()); - cy.get(cesc2("#/fmaxcdva")).should("have.text", f100.toString()); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/f"].stateValues.domain).eqls([ - [ - "interval", - ["tuple", -Infinity, Infinity], - ["tuple", false, false], - ], - ]); - - expect(stateVariables["/fmin"].stateValues.xs).eqls([-2, -8]); - expect(stateVariables["/fminl"].stateValues.value).eq(-2); - expect(stateVariables["/fminla"].stateValues.value).eq(-2); - expect(stateVariables["/fminv"].stateValues.value).eq(-8); - expect(stateVariables["/fminva"].stateValues.value).eq(-8); - - expect(stateVariables["/fmincd"].stateValues.xs).eqls([-2, -8]); - expect(stateVariables["/fmincdl"].stateValues.value).eq(-2); - expect(stateVariables["/fmincdla"].stateValues.value).eq(-2); - expect(stateVariables["/fmincdv"].stateValues.value).eq(-8); - expect(stateVariables["/fmincdva"].stateValues.value).eq(-8); - - expect(stateVariables["/fmax"]).eq(undefined); - assert.isNaN(stateVariables["/fmaxl"].stateValues.value); - assert.isNaN(stateVariables["/fmaxla"].stateValues.value); - assert.isNaN(stateVariables["/fmaxv"].stateValues.value); - assert.isNaN(stateVariables["/fmaxva"].stateValues.value); - - expect(stateVariables["/fmaxcd"].stateValues.xs).eqls([-100, f100]); - expect(stateVariables["/fmaxcdl"].stateValues.value).eq(-100); - expect(stateVariables["/fmaxcdla"].stateValues.value).eq(-100); - expect(stateVariables["/fmaxcdv"].stateValues.value).eq(f100); - expect(stateVariables["/fmaxcdva"].stateValues.value).eq(f100); - }); - }); - - it("global extrema, double well, different domains", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - x^4-8x^2+8 - x^4-8x^2+8 - x^4-8x^2+8 - x^4-8x^2+8 - x^4-8x^2+8 - -

f1 domain:

-

f2 domain:

-

f3 domain:

-

f4 domain:

-

f5 domain:

-

f1: $f1.globalMinimum{assignNames="f1min"}, $f1.globalInfimum{assignNames="f1mincd"}, $f1.globalMaximum{assignNames="f1max"}, $f1.globalSupremum{assignNames="f1maxcd"}

-

f2: $f2.globalMinimum{assignNames="f2min"}, $f2.globalInfimum{assignNames="f2mincd"}, $f2.globalMaximum{assignNames="f2max"}, $f2.globalSupremum{assignNames="f2maxcd"}

-

f3: $f3.globalMinimum{assignNames="f3min"}, $f3.globalInfimum{assignNames="f3mincd"}, $f3.globalMaximum{assignNames="f3max"}, $f3.globalSupremum{assignNames="f3maxcd"}

-

f4: $f4.globalMinimum{assignNames="f4min"}, $f4.globalInfimum{assignNames="f4mincd"}, $f4.globalMaximum{assignNames="f4max"}, $f4.globalSupremum{assignNames="f4maxcd"}

-

f5: $f5.globalMinimum{assignNames="f5min"}, $f5.globalInfimum{assignNames="f5mincd"}, $f5.globalMaximum{assignNames="f5max"}, $f5.globalSupremum{assignNames="f5maxcd"}

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/f1domain") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−2,∞)"); - cy.get(cesc2("#/f2domain") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−∞,2)"); - cy.get(cesc2("#/f3domain") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,2]"); - cy.get(cesc2("#/f4domain") + " .mjx-mrow") - .eq(0) - .should("have.text", "[0,2)"); - cy.get(cesc2("#/f5domain") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−0.01,2.01)"); - - let f198 = 198 ** 4 - 8 * 198 ** 2 + 8; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/f1"].stateValues.domain).eqls([ - ["interval", ["tuple", -2, Infinity], ["tuple", false, false]], - ]); - expect(stateVariables["/f2"].stateValues.domain).eqls([ - ["interval", ["tuple", -Infinity, 2], ["tuple", false, false]], - ]); - expect(stateVariables["/f3"].stateValues.domain).eqls([ - ["interval", ["tuple", 0, 2], ["tuple", false, true]], - ]); - expect(stateVariables["/f4"].stateValues.domain).eqls([ - ["interval", ["tuple", 0, 2], ["tuple", true, false]], - ]); - expect(stateVariables["/f5"].stateValues.domain).eqls([ - ["interval", ["tuple", -0.01, 2.01], ["tuple", false, false]], - ]); - - expect(stateVariables["/f1min"].stateValues.xs).eqls([2, -8]); - expect(stateVariables["/f1mincd"].stateValues.xs).eqls([2, -8]); - expect(stateVariables["/f1max"]).eq(undefined); - expect(stateVariables["/f1maxcd"].stateValues.xs).eqls([198, f198]); - - expect(stateVariables["/f2min"].stateValues.xs).eqls([-2, -8]); - expect(stateVariables["/f2mincd"].stateValues.xs).eqls([-2, -8]); - expect(stateVariables["/f2max"]).eq(undefined); - expect(stateVariables["/f2maxcd"].stateValues.xs).eqls([ - -198, - f198, - ]); - - expect(stateVariables["/f3min"].stateValues.xs).eqls([2, -8]); - expect(stateVariables["/f3mincd"].stateValues.xs).eqls([2, -8]); - expect(stateVariables["/f3max"]).eq(undefined); - expect(stateVariables["/f3maxcd"].stateValues.xs).eqls([0, 8]); - - expect(stateVariables["/f4min"]).eq(undefined); - expect(stateVariables["/f4mincd"].stateValues.xs).eqls([2, -8]); - expect(stateVariables["/f4max"].stateValues.xs).eqls([0, 8]); - expect(stateVariables["/f4maxcd"].stateValues.xs).eqls([0, 8]); - - expect(stateVariables["/f5min"].stateValues.xs[0]).closeTo(2, 1e-5); - expect(stateVariables["/f5min"].stateValues.xs[1]).closeTo( - -8, - 1e-5, - ); - expect(stateVariables["/f5mincd"].stateValues.xs[0]).closeTo( - 2, - 1e-5, - ); - expect(stateVariables["/f5mincd"].stateValues.xs[1]).closeTo( - -8, - 1e-5, - ); - expect(stateVariables["/f5max"].stateValues.xs[0]).closeTo(0, 1e-5); - expect(stateVariables["/f5max"].stateValues.xs[1]).closeTo(8, 1e-5); - expect(stateVariables["/f5maxcd"].stateValues.xs[0]).closeTo( - 0, - 1e-5, - ); - expect(stateVariables["/f5maxcd"].stateValues.xs[1]).closeTo( - 8, - 1e-5, - ); - }); - }); - - it("global extrema, sin, different domains", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - sin(x) - sin(x) - sin(x) - sin(x) - sin(x) - -

f1: $f1.globalMinimum{assignNames="f1min"}, $f1.globalInfimum{assignNames="f1mincd"}, $f1.globalMaximum{assignNames="f1max"}, $f1.globalSupremum{assignNames="f1maxcd"}

-

f2: $f2.globalMinimum{assignNames="f2min"}, $f2.globalInfimum{assignNames="f2mincd"}, $f2.globalMaximum{assignNames="f2max"}, $f2.globalSupremum{assignNames="f2maxcd"}

-

f3: $f3.globalMinimum{assignNames="f3min"}, $f3.globalInfimum{assignNames="f3mincd"}, $f3.globalMaximum{assignNames="f3max"}, $f3.globalSupremum{assignNames="f3maxcd"}

-

f4: $f4.globalMinimum{assignNames="f4min"}, $f4.globalInfimum{assignNames="f4mincd"}, $f4.globalMaximum{assignNames="f4max"}, $f4.globalSupremum{assignNames="f4maxcd"}

-

f5: $f5.globalMinimum{assignNames="f5min"}, $f5.globalInfimum{assignNames="f5mincd"}, $f5.globalMaximum{assignNames="f5max"}, $f5.globalSupremum{assignNames="f5maxcd"}

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/f1min"].stateValues.xs).eqls([ - -Math.PI / 2, - -1, - ]); - expect(stateVariables["/f1mincd"].stateValues.xs).eqls([ - -Math.PI / 2, - -1, - ]); - expect(stateVariables["/f1max"].stateValues.xs).eqls([ - Math.PI / 2, - 1, - ]); - expect(stateVariables["/f1maxcd"].stateValues.xs).eqls([ - Math.PI / 2, - 1, - ]); - - expect(stateVariables["/f2min"]).eq(undefined); - expect(stateVariables["/f2mincd"].stateValues.xs).eqls([ - -Math.PI / 2, - -1, - ]); - expect(stateVariables["/f2max"].stateValues.xs).eqls([ - Math.PI / 2, - 1, - ]); - expect(stateVariables["/f2maxcd"].stateValues.xs).eqls([ - Math.PI / 2, - 1, - ]); - - expect(stateVariables["/f3min"].stateValues.xs).eqls([ - (3 * Math.PI) / 2, - -1, - ]); - expect(stateVariables["/f3mincd"].stateValues.xs).eqls([ - (3 * Math.PI) / 2, - -1, - ]); - expect(stateVariables["/f3max"].stateValues.xs).eqls([ - Math.PI / 2, - 1, - ]); - expect(stateVariables["/f3maxcd"].stateValues.xs).eqls([ - Math.PI / 2, - 1, - ]); - - expect(stateVariables["/f4min"]).eq(undefined); - expect(stateVariables["/f4mincd"].stateValues.xs).eqls([ - -Math.PI / 2, - -1, - ]); - expect(stateVariables["/f4max"]).eq(undefined); - expect(stateVariables["/f4maxcd"].stateValues.xs).eqls([ - Math.PI / 2, - 1, - ]); - - expect(stateVariables["/f5min"].stateValues.xs).eqls([ - -Math.PI / 2, - -1, - ]); - expect(stateVariables["/f5mincd"].stateValues.xs).eqls([ - -Math.PI / 2, - -1, - ]); - expect(stateVariables["/f5max"].stateValues.xs).eqls([ - Math.PI / 2, - 1, - ]); - expect(stateVariables["/f5maxcd"].stateValues.xs).eqls([ - Math.PI / 2, - 1, - ]); - }); - }); - - it("global extrema, 1/x, different domains", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - 1/x - 1/x - 1/x - 1/x - -1/x - -

f1: $f1.globalMinimum{assignNames="f1min"}, $f1.globalInfimum{assignNames="f1mincd"}, $f1.globalMaximum{assignNames="f1max"}, $f1.globalSupremum{assignNames="f1maxcd"}

-

f2: $f2.globalMinimum{assignNames="f2min"}, $f2.globalInfimum{assignNames="f2mincd"}, $f2.globalMaximum{assignNames="f2max"}, $f2.globalSupremum{assignNames="f2maxcd"}

-

f3: $f3.globalMinimum{assignNames="f3min"}, $f3.globalInfimum{assignNames="f3mincd"}, $f3.globalMaximum{assignNames="f3max"}, $f3.globalSupremum{assignNames="f3maxcd"}

-

f4: $f4.globalMinimum{assignNames="f4min"}, $f4.globalInfimum{assignNames="f4mincd"}, $f4.globalMaximum{assignNames="f4max"}, $f4.globalSupremum{assignNames="f4maxcd"}

-

f5: $f5.globalMinimum{assignNames="f5min"}, $f5.globalInfimum{assignNames="f5mincd"}, $f5.globalMaximum{assignNames="f5max"}, $f5.globalSupremum{assignNames="f5maxcd"}

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/f1min"].stateValues.xs[0]).within( - -1e-6, - -1e-300, - ); - expect(stateVariables["/f1min"].stateValues.xs[1]).lessThan(-1e6); - expect(stateVariables["/f1mincd"].stateValues.xs).eqls( - stateVariables["/f1min"].stateValues.xs, - ); - expect(stateVariables["/f1max"].stateValues.xs[0]).within( - 1e-300, - 1e-6, - ); - expect(stateVariables["/f1max"].stateValues.xs[1]).greaterThan(1e6); - expect(stateVariables["/f1maxcd"].stateValues.xs).eqls( - stateVariables["/f1max"].stateValues.xs, - ); - - expect(stateVariables["/f2min"]).eq(undefined); - expect(stateVariables["/f2mincd"].stateValues.xs).eqls([ - 200, - 1 / 200, - ]); - expect(stateVariables["/f2max"]).eq(undefined); - expect(stateVariables["/f2maxcd"].stateValues.xs).eqls([ - 0, - Infinity, - ]); - - expect(stateVariables["/f3min"]).eq(undefined); - expect(stateVariables["/f3mincd"].stateValues.xs).eqls([ - 0, - -Infinity, - ]); - expect(stateVariables["/f3max"]).eq(undefined); - expect(stateVariables["/f3maxcd"].stateValues.xs).eqls([ - -200, - -1 / 200, - ]); - - expect(stateVariables["/f4min"].stateValues.xs[0]).within( - -1e-6, - -1e-300, - ); - expect(stateVariables["/f4min"].stateValues.xs[1]).lessThan(-1e6); - expect(stateVariables["/f4mincd"].stateValues.xs).eqls( - stateVariables["/f4min"].stateValues.xs, - ); - expect(stateVariables["/f4max"].stateValues.xs[0]).within( - 1e-300, - 1e-6, - ); - expect(stateVariables["/f4max"].stateValues.xs[1]).greaterThan(1e6); - expect(stateVariables["/f4maxcd"].stateValues.xs).eqls( - stateVariables["/f4max"].stateValues.xs, - ); - - expect(stateVariables["/f5min"]).eq(undefined); - expect(stateVariables["/f5mincd"].stateValues.xs).eqls([-1, 1]); - expect(stateVariables["/f5max"]).eq(undefined); - expect(stateVariables["/f5maxcd"].stateValues.xs).eqls([ - 0, - Infinity, - ]); - }); - }); - - it("global extrema, 1/x^2, different domains", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - 1/x^2 - 1/x^2 - 1/x^2 - 1/x^2 - -1/x^2 - -

f1: $f1.globalMinimum{assignNames="f1min"}, $f1.globalInfimum{assignNames="f1mincd"}, $f1.globalMaximum{assignNames="f1max"}, $f1.globalSupremum{assignNames="f1maxcd"}

-

f2: $f2.globalMinimum{assignNames="f2min"}, $f2.globalInfimum{assignNames="f2mincd"}, $f2.globalMaximum{assignNames="f2max"}, $f2.globalSupremum{assignNames="f2maxcd"}

-

f3: $f3.globalMinimum{assignNames="f3min"}, $f3.globalInfimum{assignNames="f3mincd"}, $f3.globalMaximum{assignNames="f3max"}, $f3.globalSupremum{assignNames="f3maxcd"}

-

f4: $f4.globalMinimum{assignNames="f4min"}, $f4.globalInfimum{assignNames="f4mincd"}, $f4.globalMaximum{assignNames="f4max"}, $f4.globalSupremum{assignNames="f4maxcd"}

-

f5: $f5.globalMinimum{assignNames="f5min"}, $f5.globalInfimum{assignNames="f5mincd"}, $f5.globalMaximum{assignNames="f5max"}, $f5.globalSupremum{assignNames="f5maxcd"}

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/f1min"]).eq(undefined); - expect(stateVariables["/f1mincd"].stateValues.xs).eqls([ - -100, - 1 / 10000, - ]); - expect(stateVariables["/f1max"].stateValues.xs[0]).within( - -1e-6, - -1e-300, - ); - expect(stateVariables["/f1max"].stateValues.xs[1]).greaterThan( - 1e12, - ); - expect(stateVariables["/f1maxcd"].stateValues.xs).eqls( - stateVariables["/f1max"].stateValues.xs, - ); - - expect(stateVariables["/f2min"]).eq(undefined); - expect(stateVariables["/f2mincd"].stateValues.xs).eqls([ - 200, - 1 / 40000, - ]); - expect(stateVariables["/f2max"]).eq(undefined); - expect(stateVariables["/f2maxcd"].stateValues.xs).eqls([ - 0, - Infinity, - ]); - - expect(stateVariables["/f3min"]).eq(undefined); - expect(stateVariables["/f3mincd"].stateValues.xs).eqls([ - -200, - 1 / 40000, - ]); - expect(stateVariables["/f3max"]).eq(undefined); - expect(stateVariables["/f3maxcd"].stateValues.xs).eqls([ - 0, - Infinity, - ]); - - expect(stateVariables["/f4min"]).eq(undefined); - expect(stateVariables["/f4mincd"].stateValues.xs).eqls([ - 100, - 1 / 10000, - ]); - expect(stateVariables["/f4max"].stateValues.xs[0]).within( - -1e-6, - -1e-300, - ); - expect(stateVariables["/f4max"].stateValues.xs[1]).greaterThan( - 1e12, - ); - expect(stateVariables["/f4maxcd"].stateValues.xs).eqls( - stateVariables["/f4max"].stateValues.xs, - ); - - expect(stateVariables["/f5min"]).eq(undefined); - expect(stateVariables["/f5mincd"].stateValues.xs).eqls([ - 0, - -Infinity, - ]); - expect(stateVariables["/f5max"]).eq(undefined); - expect(stateVariables["/f5maxcd"].stateValues.xs).eqls([-1, -1]); - }); - }); - - it("global extrema of linear interpolated function", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - - - - - - - - - -

f1 domain:

-

f2 domain:

-

f3 domain:

-

f4 domain:

-

f5 domain:

-

f6 domain:

-

f7 domain:

-

f8 domain:

- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/f1domain") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−∞,∞)"); - cy.get(cesc2("#/f2domain") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−∞,∞)"); - cy.get(cesc2("#/f3domain") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−10,−9)"); - cy.get(cesc2("#/f4domain") + " .mjx-mrow") - .eq(0) - .should("have.text", "[−7,3]"); - cy.get(cesc2("#/f5domain") + " .mjx-mrow") - .eq(0) - .should("have.text", "(9,10]"); - cy.get(cesc2("#/f6domain") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−10,−9)"); - cy.get(cesc2("#/f7domain") + " .mjx-mrow") - .eq(0) - .should("have.text", "[−7,3]"); - cy.get(cesc2("#/f8domain") + " .mjx-mrow") - .eq(0) - .should("have.text", "(9,10]"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let f1 = stateVariables["/f1"]; - let f2 = stateVariables["/f2"]; - let f3 = stateVariables["/f3"]; - let f4 = stateVariables["/f4"]; - let f5 = stateVariables["/f5"]; - let f6 = stateVariables["/f6"]; - let f7 = stateVariables["/f7"]; - let f8 = stateVariables["/f8"]; - - expect(f1.stateValues.domain).eqls([ - [ - "interval", - ["tuple", -Infinity, Infinity], - ["tuple", false, false], - ], - ]); - expect(f2.stateValues.domain).eqls([ - [ - "interval", - ["tuple", -Infinity, Infinity], - ["tuple", false, false], - ], - ]); - expect(f3.stateValues.domain).eqls([ - ["interval", ["tuple", -10, -9], ["tuple", false, false]], - ]); - expect(f4.stateValues.domain).eqls([ - ["interval", ["tuple", -7, 3], ["tuple", true, true]], - ]); - expect(f5.stateValues.domain).eqls([ - ["interval", ["tuple", 9, 10], ["tuple", false, true]], - ]); - expect(f6.stateValues.domain).eqls([ - ["interval", ["tuple", -10, -9], ["tuple", false, false]], - ]); - expect(f7.stateValues.domain).eqls([ - ["interval", ["tuple", -7, 3], ["tuple", true, true]], - ]); - expect(f8.stateValues.domain).eqls([ - ["interval", ["tuple", 9, 10], ["tuple", false, true]], - ]); - - expect(f1.stateValues.globalMinimum).eqls([]); - expect(f1.stateValues.globalInfimum).eqls([Infinity, -Infinity]); - expect(f1.stateValues.globalMaximum).eqls([]); - expect(f1.stateValues.globalSupremum).eqls([-Infinity, Infinity]); - expect(f2.stateValues.globalMinimum).eqls([]); - expect(f2.stateValues.globalInfimum).eqls([-Infinity, -Infinity]); - expect(f2.stateValues.globalMaximum).eqls([]); - expect(f2.stateValues.globalSupremum).eqls([Infinity, Infinity]); - expect(f3.stateValues.globalMinimum).eqls([]); - expect(f3.stateValues.globalInfimum).eqls([-9, 7.5]); - expect(f3.stateValues.globalMaximum).eqls([]); - expect(f3.stateValues.globalSupremum).eqls([-10, 8]); - expect(f4.stateValues.globalMinimum).eqls([3, 1.5]); - expect(f4.stateValues.globalInfimum).eqls([3, 1.5]); - expect(f4.stateValues.globalMaximum).eqls([-7, 6.5]); - expect(f4.stateValues.globalSupremum).eqls([-7, 6.5]); - expect(f5.stateValues.globalMinimum).eqls([10, -2]); - expect(f5.stateValues.globalInfimum).eqls([10, -2]); - expect(f5.stateValues.globalMaximum).eqls([]); - expect(f5.stateValues.globalSupremum).eqls([9, -1.5]); - expect(f6.stateValues.globalMinimum).eqls([]); - expect(f6.stateValues.globalInfimum).eqls([-10, -6]); - expect(f6.stateValues.globalMaximum).eqls([]); - expect(f6.stateValues.globalSupremum).eqls([-9, -5.5]); - expect(f7.stateValues.globalMinimum).eqls([-7, -4.5]); - expect(f7.stateValues.globalInfimum).eqls([-7, -4.5]); - expect(f7.stateValues.globalMaximum).eqls([3, 0.5]); - expect(f7.stateValues.globalSupremum).eqls([3, 0.5]); - expect(f8.stateValues.globalMinimum).eqls([]); - expect(f8.stateValues.globalInfimum).eqls([9, 3.5]); - expect(f8.stateValues.globalMaximum).eqls([10, 4]); - expect(f8.stateValues.globalSupremum).eqls([10, 4]); - }); - }); }); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/functioniterates.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/functioniterates.cy.js deleted file mode 100644 index 22023aae0..000000000 --- a/packages/test-cypress/cypress/e2e/tagSpecific/functioniterates.cy.js +++ /dev/null @@ -1,1245 +0,0 @@ -import me from "math-expressions"; -import { cesc, cesc2 } from "@doenet/utils"; - -function nInDOM(n) { - if (n < 0) { - return `−${Math.abs(n)}`; - } else { - return String(n); - } -} - -describe("FunctionIterates Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - // TODO: test forceNumeric and forceSymbolic? - - it("1D user-defined function", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Choose variable for function: . - Let f($x) = . - Let u = . Let n= - Then

-
    - - - - -
- -

$fformula$fis.iterates{name="iterates"}

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/l1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f1(u)=3av"); - }); - cy.get(cesc("#\\/l2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f2(u)=3va2"); - }); - cy.get(cesc("#\\/l3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f3(u)=3va3"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/l1/iter"].stateValues.value).eqls([ - "*", - 3, - "a", - "v", - ]); - expect(stateVariables["/l2/iter"].stateValues.value).eqls([ - "*", - 3, - "v", - ["^", "a", 2], - ]); - expect(stateVariables["/l3/iter"].stateValues.value).eqls([ - "*", - 3, - "v", - ["^", "a", 3], - ]); - }); - - cy.log("change function, numIterates, and initial"); - cy.get(cesc("#\\/fformula") + " textarea").type( - "{end}{backspace}{backspace}bx^2{enter}", - { force: true }, - ); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}4{enter}", { - force: true, - }); - cy.get(cesc("#\\/u") + " textarea").type( - "{end}{backspace}{backspace}w{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/l1")).should("contain.text", "f1(u)=bw2"); - - cy.get(cesc("#\\/l1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f1(u)=bw2"); - }); - cy.get(cesc("#\\/l2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f2(u)=b3w4"); - }); - cy.get(cesc("#\\/l3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f3(u)=b7w8"); - }); - cy.get(cesc("#\\/l4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f4(u)=b15w16"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/l1/iter"].stateValues.value).eqls([ - "*", - "b", - ["^", "w", 2], - ]); - expect(stateVariables["/l2/iter"].stateValues.value).eqls([ - "*", - ["^", "b", 3], - ["^", "w", 4], - ]); - expect(stateVariables["/l3/iter"].stateValues.value).eqls([ - "*", - ["^", "b", 7], - ["^", "w", 8], - ]); - expect(stateVariables["/l4/iter"].stateValues.value).eqls([ - "*", - ["^", "b", 15], - ["^", "w", 16], - ]); - }); - - cy.log("change variable"); - cy.get(cesc("#\\/x") + " textarea").type("{end}{backspace}y{enter}", { - force: true, - }); - - cy.get(cesc("#\\/l1")).should("contain.text", "f1(u)=bx2"); - - cy.get(cesc("#\\/l1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f1(u)=bx2"); - }); - cy.get(cesc("#\\/l2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f2(u)=bx2"); - }); - cy.get(cesc("#\\/l3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f3(u)=bx2"); - }); - cy.get(cesc("#\\/l4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f4(u)=bx2"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/l1/iter"].stateValues.value).eqls([ - "*", - "b", - ["^", "x", 2], - ]); - expect(stateVariables["/l2/iter"].stateValues.value).eqls([ - "*", - "b", - ["^", "x", 2], - ]); - expect(stateVariables["/l3/iter"].stateValues.value).eqls([ - "*", - "b", - ["^", "x", 2], - ]); - expect(stateVariables["/l4/iter"].stateValues.value).eqls([ - "*", - "b", - ["^", "x", 2], - ]); - }); - - cy.log("change function to match variable"); - cy.get(cesc("#\\/fformula") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}y+q{enter}", - { force: true }, - ); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}5{enter}", { - force: true, - }); - - cy.get(cesc("#\\/l5")).should("contain.text", "f5(u)=5q+w"); - - cy.get(cesc("#\\/l1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f1(u)=q+w"); - }); - cy.get(cesc("#\\/l2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f2(u)=2q+w"); - }); - cy.get(cesc("#\\/l3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f3(u)=3q+w"); - }); - cy.get(cesc("#\\/l4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f4(u)=4q+w"); - }); - cy.get(cesc("#\\/l5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f5(u)=5q+w"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/l1/iter"].stateValues.value).eqls([ - "+", - "q", - "w", - ]); - expect(stateVariables["/l2/iter"].stateValues.value).eqls([ - "+", - ["*", 2, "q"], - "w", - ]); - expect(stateVariables["/l3/iter"].stateValues.value).eqls([ - "+", - ["*", 3, "q"], - "w", - ]); - expect(stateVariables["/l4/iter"].stateValues.value).eqls([ - "+", - ["*", 4, "q"], - "w", - ]); - expect(stateVariables["/l5/iter"].stateValues.value).eqls([ - "+", - ["*", 5, "q"], - "w", - ]); - }); - }); - - it("1D user-defined numerical function", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Choose variable for function: . - Let f($x) = . - Let u = . Let n= - Then

-
    - - - - -
- -

$fformula$fis.iterates{name="iterates"}

- - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/l1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f1(u)=6"); - }); - cy.get(cesc("#\\/l2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f2(u)=18"); - }); - cy.get(cesc("#\\/l3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f3(u)=54"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/l1/iter"].stateValues.value).eqls(6); - expect(stateVariables["/l2/iter"].stateValues.value).eqls(18); - expect(stateVariables["/l3/iter"].stateValues.value).eqls(54); - }); - - cy.log("change function, numIterates, and initial"); - cy.get(cesc("#\\/fformula") + " textarea").type( - "{end}{backspace}{backspace}2x^2{enter}", - { force: true }, - ); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}4{enter}", { - force: true, - }); - cy.get(cesc("#\\/u") + " textarea").type( - "{end}{backspace}{backspace}1/4{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/l1")).should("contain.text", "f1(u)=0.125"); - - cy.get(cesc("#\\/l1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f1(u)=0.125"); - }); - cy.get(cesc("#\\/l2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f2(u)=0.03125"); - }); - cy.get(cesc("#\\/l3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f3(u)=0.001953125"); - }); - cy.get(cesc("#\\/l4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f4(u)=0.000007629394531"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/l1/iter"].stateValues.value).eqls(0.125); - expect(stateVariables["/l2/iter"].stateValues.value).eqls(0.03125); - expect(stateVariables["/l3/iter"].stateValues.value).eqls( - 0.001953125, - ); - expect(stateVariables["/l4/iter"].stateValues.value).eqls( - 0.00000762939453125, - ); - }); - - cy.log("change variable"); - cy.get(cesc("#\\/x") + " textarea").type("{end}{backspace}y{enter}", { - force: true, - }); - - cy.get(cesc("#\\/l1")).should("contain.text", "f1(u)=NaN"); - - cy.get(cesc("#\\/l1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f1(u)=NaN"); - }); - cy.get(cesc("#\\/l2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f2(u)=NaN"); - }); - cy.get(cesc("#\\/l3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f3(u)=NaN"); - }); - cy.get(cesc("#\\/l4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f4(u)=NaN"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/l1/iter"].stateValues.value).eqls(NaN); - expect(stateVariables["/l2/iter"].stateValues.value).eqls(NaN); - expect(stateVariables["/l3/iter"].stateValues.value).eqls(NaN); - expect(stateVariables["/l4/iter"].stateValues.value).eqls(NaN); - }); - - cy.log("change function to match variable"); - cy.get(cesc("#\\/fformula") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}y+5{enter}", - { force: true }, - ); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}5{enter}", { - force: true, - }); - - cy.get(cesc("#\\/l5")).should("contain.text", "f5(u)=25.25"); - - cy.get(cesc("#\\/l1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f1(u)=5.25"); - }); - cy.get(cesc("#\\/l2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f2(u)=10.25"); - }); - cy.get(cesc("#\\/l3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f3(u)=15.25"); - }); - cy.get(cesc("#\\/l4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f4(u)=20.25"); - }); - cy.get(cesc("#\\/l5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("f5(u)=25.25"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/l1/iter"].stateValues.value).eqls(5.25); - expect(stateVariables["/l2/iter"].stateValues.value).eqls(10.25); - expect(stateVariables["/l3/iter"].stateValues.value).eqls(15.25); - expect(stateVariables["/l4/iter"].stateValues.value).eqls(20.25); - expect(stateVariables["/l5/iter"].stateValues.value).eqls(25.25); - }); - }); - - it("2D linear function", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

variables: and . - a = , b = , c = , d = . - f($x, $y) = ($a$x+$b$y, $c$x+$d$y) - u = n=

- - -

Iterates: $fis.iterates{name="iterates"}

- $n.value{assignNames="n2"} - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - function checkIterates({ a, b, c, d, u1, u2, n }) { - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let A = me.math.matrix([ - [a, b], - [c, d], - ]); - let x = me.math.matrix([[u1], [u2]]); - - let iterNames = stateVariables["/iterates"].replacements.map( - (x) => x.componentName, - ); - let iterAnchors = iterNames.map((x) => cesc2("#" + x)); - - for (let i = 0; i < n; i++) { - x = me.math.multiply(A, x); - let x1 = me.math.subset(x, me.math.index(0, 0)); - let x2 = me.math.subset(x, me.math.index(1, 0)); - expect(stateVariables[iterNames[i]].stateValues.value).eqls( - ["vector", x1, x2], - ); - cy.get(iterAnchors[i]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal( - `(${x1},${x2})`, - ); - }); - } - }); - } - - checkIterates({ a: 3, b: -2, c: 1, d: 4, u1: 2, u2: 1, n: 3 }); - - cy.log(`change values`); - cy.get(cesc("#\\/x") + " textarea").type("{end}{backspace}q{enter}", { - force: true, - }); - cy.get(cesc("#\\/y") + " textarea").type("{end}{backspace}r{enter}", { - force: true, - }); - cy.get(cesc("#\\/a") + " textarea").type( - "{end}{backspace}{backspace}-4{enter}", - { force: true }, - ); - cy.get(cesc("#\\/b") + " textarea").type( - "{end}{backspace}{backspace}7{enter}", - { force: true }, - ); - cy.get(cesc("#\\/c") + " textarea").type( - "{end}{backspace}{backspace}6{enter}", - { force: true }, - ); - cy.get(cesc("#\\/d") + " textarea").type( - "{end}{backspace}{backspace}-1{enter}", - { force: true }, - ); - cy.get(cesc("#\\/u") + " textarea").type( - "{end}{leftArrow}{backspace}{backspace}{backspace}-8, 9{enter}", - { force: true }, - ); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}5{enter}", { - force: true, - }); - - cy.get(cesc("#\\/n2")).should("contain.text", "5"); - - checkIterates({ a: -4, b: 7, c: 6, d: -1, u1: -8, u2: 9, n: 5 }); - }); - - it("2D linear function, with alt vectors", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

variables: and . - a = , b = , c = , d = . - f($x, $y) = ⟨$a$x+$b$y, $c$x+$d$y⟩ - u = n=

- - -

Iterates: $fis.iterates{name="iterates"}

- $n.value{assignNames="n2"} - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - function checkIterates({ a, b, c, d, u1, u2, n }) { - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let A = me.math.matrix([ - [a, b], - [c, d], - ]); - let x = me.math.matrix([[u1], [u2]]); - - let iterNames = stateVariables["/iterates"].replacements.map( - (x) => x.componentName, - ); - let iterAnchors = iterNames.map((x) => cesc2("#" + x)); - - for (let i = 0; i < n; i++) { - x = me.math.multiply(A, x); - let x1 = me.math.subset(x, me.math.index(0, 0)); - let x2 = me.math.subset(x, me.math.index(1, 0)); - expect(stateVariables[iterNames[i]].stateValues.value).eqls( - ["vector", x1, x2], - ); - cy.get(iterAnchors[i]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal( - `(${x1},${x2})`, - ); - }); - } - }); - } - - checkIterates({ a: 3, b: -2, c: 1, d: 4, u1: 2, u2: 1, n: 3 }); - - cy.log(`change values`); - cy.get(cesc("#\\/x") + " textarea").type("{end}{backspace}q{enter}", { - force: true, - }); - cy.get(cesc("#\\/y") + " textarea").type("{end}{backspace}r{enter}", { - force: true, - }); - cy.get(cesc("#\\/a") + " textarea").type( - "{end}{backspace}{backspace}-4{enter}", - { force: true }, - ); - cy.get(cesc("#\\/b") + " textarea").type( - "{end}{backspace}{backspace}7{enter}", - { force: true }, - ); - cy.get(cesc("#\\/c") + " textarea").type( - "{end}{backspace}{backspace}6{enter}", - { force: true }, - ); - cy.get(cesc("#\\/d") + " textarea").type( - "{end}{backspace}{backspace}-1{enter}", - { force: true }, - ); - cy.get(cesc("#\\/u") + " textarea").type( - "{end}{leftArrow}{backspace}{backspace}{backspace}-8, 9{enter}", - { force: true }, - ); - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}5{enter}", { - force: true, - }); - - cy.get(cesc("#\\/n2")).should("contain.text", "5"); - - checkIterates({ a: -4, b: 7, c: 6, d: -1, u1: -8, u2: 9, n: 5 }); - }); - - it("warning for scalar function of two variables", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - f(x, y) = x+y - - -

Iterates: $fis.iterates

- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_p1")).should("contain.text", "Iterates: \uff3f"); - - cy.window().then(async (win) => { - let errorWarnings = await win.returnErrorWarnings1(); - - expect(errorWarnings.errors.length).eq(0); - expect(errorWarnings.warnings.length).eq(1); - - expect(errorWarnings.warnings[0].message).contain( - "Function iterates are possible only if the number of inputs of the function is equal to the number of outputs. This function has 2 inputs and 1 output", - ); - expect(errorWarnings.warnings[0].level).eq(1); - expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(4); - expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(3); - expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(4); - expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(84); - }); - }); - - it("change dimensions", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

variables: . - f($vars) = . - u =

- -

Iterates: $fis.iterates{name="iterates"}

- - -

$vars$fformula

- - $vars.value{assignNames="vars2"} - $fformula.value{assignNames="fformula2"} - $u.value{assignNames="u2"} - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let iterNames = stateVariables["/iterates"].replacements.map( - (x) => x.componentName, - ); - let iterAnchors = iterNames.map((x) => cesc2("#" + x)); - - expect(stateVariables["/fis"].stateValues.numDimensions).eq(2); - expect(stateVariables[iterNames[0]].stateValues.value).eqls([ - "vector", - 2, - 3, - ]); - expect(stateVariables[iterNames[1]].stateValues.value).eqls([ - "vector", - 6, - 5, - ]); - expect(stateVariables[iterNames[2]].stateValues.value).eqls([ - "vector", - 30, - 11, - ]); - - cy.get(iterAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal(`(2,3)`); - }); - cy.get(iterAnchors[1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal(`(6,5)`); - }); - cy.get(iterAnchors[2]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal(`(30,11)`); - }); - }); - - cy.log(`add component to function`); - cy.get(cesc("#\\/fformula") + " textarea").type( - "{end}{leftArrow}z, x-z{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/fformula2")).should("contain.text", "x+yz,"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let iterNames = stateVariables["/iterates"].replacements.map( - (x) => x.componentName, - ); - let iterAnchors = iterNames.map((x) => cesc2("#" + x)); - - expect(stateVariables["/fis"].stateValues.numDimensions).eq(0); - expect(stateVariables[iterNames[0]].stateValues.value).eqls( - "\uff3f", - ); - expect(stateVariables[iterNames[1]].stateValues.value).eqls( - "\uff3f", - ); - expect(stateVariables[iterNames[2]].stateValues.value).eqls( - "\uff3f", - ); - - cy.get(iterAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal("\uff3f"); - }); - cy.get(iterAnchors[1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal("\uff3f"); - }); - cy.get(iterAnchors[2]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal("\uff3f"); - }); - }); - - cy.log(`add variable to function`); - cy.get(cesc("#\\/vars") + " textarea").type("{end}, z{enter}", { - force: true, - }); - cy.get(cesc("#\\/vars2")).should("contain.text", "x,y,z"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let iterNames = stateVariables["/iterates"].replacements.map( - (x) => x.componentName, - ); - let iterAnchors = iterNames.map((x) => cesc2("#" + x)); - - expect(stateVariables["/fis"].stateValues.numDimensions).eq(3); - expect(stateVariables[iterNames[0]].stateValues.value).eqls( - "\uff3f", - ); - expect(stateVariables[iterNames[1]].stateValues.value).eqls( - "\uff3f", - ); - expect(stateVariables[iterNames[2]].stateValues.value).eqls( - "\uff3f", - ); - - cy.get(iterAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal("\uff3f"); - }); - cy.get(iterAnchors[1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal("\uff3f"); - }); - cy.get(iterAnchors[2]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal("\uff3f"); - }); - }); - - cy.log(`add component to initial condition`); - cy.get(cesc("#\\/u") + " textarea").type( - "{end}{leftArrow}, -4{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/u2")).should("contain.text", "2,1,"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let iterNames = stateVariables["/iterates"].replacements.map( - (x) => x.componentName, - ); - let iterAnchors = iterNames.map((x) => cesc2("#" + x)); - - expect(stateVariables["/fis"].stateValues.numDimensions).eq(3); - expect(stateVariables[iterNames[0]].stateValues.value).eqls([ - "vector", - 2, - -2, - 6, - ]); - expect(stateVariables[iterNames[1]].stateValues.value).eqls([ - "vector", - -4, - -10, - -4, - ]); - expect(stateVariables[iterNames[2]].stateValues.value).eqls([ - "vector", - 40, - 36, - 0, - ]); - - cy.get(iterAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal(`(2,-2,6)`); - }); - cy.get(iterAnchors[1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal(`(-4,-10,-4)`); - }); - cy.get(iterAnchors[2]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal(`(40,36,0)`); - }); - }); - }); - - it("change dimensions, numerical", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

variables: . - f($vars) = . - u =

- -

Iterates: $fis.iterates{name="iterates"}

- - -

$vars$fformula

- $u.value{assignNames="u2"} - $fformula.value{assignNames="fformula2"} - $vars.value{assignNames="vars2"} - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let iterNames = stateVariables["/iterates"].replacements.map( - (x) => x.componentName, - ); - let iterAnchors = iterNames.map((x) => cesc2("#" + x)); - - expect(stateVariables["/fis"].stateValues.numDimensions).eq(2); - expect(stateVariables[iterNames[0]].stateValues.value).eqls([ - "vector", - 2, - 3, - ]); - expect(stateVariables[iterNames[1]].stateValues.value).eqls([ - "vector", - 6, - 5, - ]); - expect(stateVariables[iterNames[2]].stateValues.value).eqls([ - "vector", - 30, - 11, - ]); - - cy.get(iterAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal(`(2,3)`); - }); - cy.get(iterAnchors[1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal(`(6,5)`); - }); - cy.get(iterAnchors[2]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal(`(30,11)`); - }); - }); - - cy.log(`non-numeric initial condition`); - cy.get(cesc("#\\/u") + " textarea").type("{end}{leftArrow}a{enter}", { - force: true, - }); - cy.get(cesc("#\\/u2")).should("contain.text", "(2,1a)"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let iterNames = stateVariables["/iterates"].replacements.map( - (x) => x.componentName, - ); - let iterAnchors = iterNames.map((x) => cesc2("#" + x)); - - expect(stateVariables["/fis"].stateValues.numDimensions).eq(2); - - cy.get(iterAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal(`(NaN,NaN)`); - }); - cy.get(iterAnchors[1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal(`(NaN,NaN)`); - }); - cy.get(iterAnchors[2]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal(`(NaN,NaN)`); - }); - }); - - cy.log(`add component to function`); - cy.get(cesc("#\\/u") + " textarea").type("{backspace}{enter}", { - force: true, - }); - cy.get(cesc("#\\/fformula") + " textarea").type( - "{end}{leftArrow}z, x-z{enter}", - { force: true }, - ); - cy.get(cesc("#\\/fformula2")).should("contain.text", "x+yz,"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let iterNames = stateVariables["/iterates"].replacements.map( - (x) => x.componentName, - ); - let iterAnchors = iterNames.map((x) => cesc2("#" + x)); - - expect(stateVariables["/fis"].stateValues.numDimensions).eq(0); - expect(stateVariables[iterNames[0]].stateValues.value).eqls( - "\uff3f", - ); - expect(stateVariables[iterNames[1]].stateValues.value).eqls( - "\uff3f", - ); - expect(stateVariables[iterNames[2]].stateValues.value).eqls( - "\uff3f", - ); - - cy.get(iterAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal("\uff3f"); - }); - cy.get(iterAnchors[1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal("\uff3f"); - }); - cy.get(iterAnchors[2]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal("\uff3f"); - }); - }); - - cy.log(`add variable to function`); - cy.get(cesc("#\\/vars") + " textarea").type("{end}, z{enter}", { - force: true, - }); - cy.get(cesc("#\\/vars2")).should("contain.text", "x,y,z"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let iterNames = stateVariables["/iterates"].replacements.map( - (x) => x.componentName, - ); - let iterAnchors = iterNames.map((x) => cesc2("#" + x)); - - expect(stateVariables["/fis"].stateValues.numDimensions).eq(3); - expect(stateVariables[iterNames[0]].stateValues.value).eqls( - "\uff3f", - ); - expect(stateVariables[iterNames[1]].stateValues.value).eqls( - "\uff3f", - ); - expect(stateVariables[iterNames[2]].stateValues.value).eqls( - "\uff3f", - ); - - cy.get(iterAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal("\uff3f"); - }); - cy.get(iterAnchors[1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal("\uff3f"); - }); - cy.get(iterAnchors[2]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal("\uff3f"); - }); - }); - - cy.log(`add component to initial condition`); - cy.get(cesc("#\\/u") + " textarea").type( - "{end}{leftArrow}, -4{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/u2")).should("contain.text", "(2,1,"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let iterNames = stateVariables["/iterates"].replacements.map( - (x) => x.componentName, - ); - let iterAnchors = iterNames.map((x) => cesc2("#" + x)); - - expect(stateVariables["/fis"].stateValues.numDimensions).eq(3); - expect(stateVariables[iterNames[0]].stateValues.value).eqls([ - "vector", - 2, - -2, - 6, - ]); - expect(stateVariables[iterNames[1]].stateValues.value).eqls([ - "vector", - -4, - -10, - -4, - ]); - expect(stateVariables[iterNames[2]].stateValues.value).eqls([ - "vector", - 40, - 36, - 0, - ]); - - cy.get(iterAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal(`(2,-2,6)`); - }); - cy.get(iterAnchors[1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal(`(-4,-10,-4)`); - }); - cy.get(iterAnchors[2]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.replace(/−/g, "-")).equal(`(40,36,0)`); - }); - }); - }); -}); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/graph.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/graph.cy.js index e6e664e7c..e537a9a32 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/graph.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/graph.cy.js @@ -1,9 +1,4 @@ -import { - cesc, - cesc2, - widthsBySize, - createFunctionFromDefinition, -} from "@doenet/utils"; +import { cesc } from "@doenet/utils"; describe("Graph Tag Tests", function () { beforeEach(() => { @@ -11,130 +6,6 @@ describe("Graph Tag Tests", function () { cy.visit("/"); }); - it.skip("string sugared to curve in graph", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x^2 - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let curve = stateVariables["/_graph1"].activeChildren[0]; - expect(curve.stateValues.flipFunction).eq(false); - expect(curve.stateValues.fs[0](-2)).eq(4); - expect(curve.stateValues.fs[0](3)).eq(9); - }); - }); - - it.skip("y = function string sugared to curve in graph", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - y=x^2 - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let curve = stateVariables["/_graph1"].activeChildren[0]; - let functioncurve = curve.activeChildren[0]; - expect(curve.stateValues.variables[0].tree).eq("x"); - expect(curve.stateValues.variables[1].tree).eq("y"); - expect(functioncurve.stateValues.variables[0].tree).eq("x"); - expect(functioncurve.stateValues.variables[1].tree).eq("y"); - expect(functioncurve.stateValues.flipFunction).eq(false); - expect(functioncurve.stateValues.f(-2)).eq(4); - expect(functioncurve.stateValues.f(3)).eq(9); - }); - }); - - it.skip("inverse function string sugared to curve in graph", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - y^2=x - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let curve = stateVariables["/_graph1"].activeChildren[0]; - let functioncurve = curve.activeChildren[0]; - expect(curve.stateValues.variables[0].tree).eq("x"); - expect(curve.stateValues.variables[1].tree).eq("y"); - expect(functioncurve.stateValues.variables[0].tree).eq("x"); - expect(functioncurve.stateValues.variables[1].tree).eq("y"); - expect(functioncurve.stateValues.flipFunction).eq(true); - expect(functioncurve.stateValues.f(-2)).eq(4); - expect(functioncurve.stateValues.f(3)).eq(9); - }); - }); - - it("functions sugared to curves in graph", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - x^2 - t^3 - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let curve1Name = - stateVariables["/_graph1"].activeChildren[0].componentName; - let curve2Name = - stateVariables["/_graph1"].activeChildren[1].componentName; - - let f1 = createFunctionFromDefinition( - stateVariables[curve1Name].stateValues.fDefinitions[0], - ); - let f2 = createFunctionFromDefinition( - stateVariables[curve2Name].stateValues.fDefinitions[0], - ); - expect(f1(-2)).eq(4); - expect(f1(3)).eq(9); - expect(f2(-2)).eq(-8); - expect(f2(3)).eq(27); - expect(stateVariables[curve1Name].stateValues.label).eq(""); - expect(stateVariables[curve2Name].stateValues.label).eq("g"); - expect(stateVariables[curve1Name].stateValues.styleNumber).eq(1); - expect(stateVariables[curve2Name].stateValues.styleNumber).eq(2); - }); - }); - it("changing bounding box", () => { cy.window().then(async (win) => { win.postMessage( @@ -321,1857 +192,156 @@ describe("Graph Tag Tests", function () { }); }); - it("labels and positioning", () => { + it("tick scale factor", () => { cy.window().then(async (win) => { win.postMessage( { doenetML: ` a - - $xlabel$ylabel - - - - - xlabel: - position: - - left - right - - - - ylabel: - position: - - top - bottom - - - alignment: - - left - right - - - - - `, - }, - "*", - ); - }); + - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load + + + - // not sure what to test as don't know how to check renderer... + + + - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g"].stateValues.xlabel).eq("x"); - expect(stateVariables["/g"].stateValues.xlabelPosition).eq("right"); - expect(stateVariables["/g"].stateValues.ylabel).eq("y"); - expect(stateVariables["/g"].stateValues.ylabelPosition).eq("top"); - expect(stateVariables["/g"].stateValues.ylabelAlignment).eq("left"); - }); + - cy.get(cesc("#\\/xlabel_input")).clear().type("hello{enter}"); - cy.get(cesc("#\\/ylabel_input")).clear().type("bye{enter}"); - cy.get(cesc("#\\/xlabelpos")).select("left"); - cy.get(cesc("#\\/ylabelpos")).select("bottom"); - cy.get(cesc("#\\/ylabelalign")).select("right"); + $ignorebad.xmin{assignNames="xmin"} + $ignorebad.xmax{assignNames="xmax"} + $ignorebad.ymin{assignNames="ymin"} + $ignorebad.ymax{assignNames="ymax"} - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g"].stateValues.xlabel).eq("hello"); - expect(stateVariables["/g"].stateValues.xlabelPosition).eq("left"); - expect(stateVariables["/g"].stateValues.ylabel).eq("bye"); - expect(stateVariables["/g"].stateValues.ylabelPosition).eq( - "bottom", - ); - expect(stateVariables["/g"].stateValues.ylabelAlignment).eq( - "right", - ); - }); - }); - it("change essential xlable and ylabel", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - -

-

-

x-label: $g.xlabel

-

y-label: $g.ylabel

`, }, "*", ); }); - cy.get(cesc("#\\/pxlabel")).should("have.text", "x-label: "); - cy.get(cesc("#\\/pylabel")).should("have.text", "y-label: "); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g"].stateValues.xlabel).eq(""); - expect(stateVariables["/g"].stateValues.ylabel).eq(""); - }); - - cy.get(cesc("#\\/uvx")).click(); - cy.get(cesc("#\\/pxlabel")).should("have.text", "x-label: s"); - cy.get(cesc("#\\/uvy")).click(); - cy.get(cesc("#\\/pylabel")).should("have.text", "y-label: t"); + cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g"].stateValues.xlabel).eq("s"); - expect(stateVariables["/g"].stateValues.ylabel).eq("t"); - }); - }); + // Note: these are brittle tests and could start failing if internals of jsxgraph changes - it("identical axis scales, with given aspect ratio", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Aspect ratio:

+ cy.get(cesc("#\\/none")).should("not.contain.text", "π"); + cy.get(cesc("#\\/none")).should("not.contain.text", "e"); + cy.get(cesc("#\\/none")).should("contain.text", "68"); + cy.get(cesc("#\\/none")).should("contain.text", "−2−4−6−8"); - + cy.get(cesc("#\\/xpi")).should("contain.text", "π2π3π"); + cy.get(cesc("#\\/xpi")).should("contain.text", "−π−2π−3π"); + cy.get(cesc("#\\/xpi")).should("contain.text", "24"); + cy.get(cesc("#\\/xpi")).should("contain.text", "68"); + cy.get(cesc("#\\/xpi")).should("contain.text", "−2−4−6−8"); -

xmin: $g.xmin{assignNames="xmin"}

-

xmax: $g.xmax{assignNames="xmax"}

-

ymin: $g.ymin{assignNames="ymin"}

-

ymax: $g.ymax{assignNames="ymax"}

- - `, - }, - "*", - ); - }); + cy.get(cesc("#\\/ypi")).should("contain.text", "π2π3π"); + cy.get(cesc("#\\/ypi")).should("contain.text", "−π−2π−3π"); + cy.get(cesc("#\\/ypi")).should("contain.text", "24"); + cy.get(cesc("#\\/ypi")).should("contain.text", "68"); + cy.get(cesc("#\\/ypi")).should("contain.text", "−2−4−6−8"); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load + cy.get(cesc("#\\/bothpi")).should("contain.text", "π2π3π"); + cy.get(cesc("#\\/bothpi")).should("contain.text", "−π−2π−3π"); + cy.get(cesc("#\\/bothpi")).should("not.contain.text", "24"); + cy.get(cesc("#\\/bothpi")).should("not.contain.text", "68"); + cy.get(cesc("#\\/bothpi")).should("not.contain.text", "−2−4−6−8"); - function checkLimits(xmin, xmax, ymin, ymax) { - cy.get(cesc("#\\/xmin")).should("have.text", String(xmin)); - cy.get(cesc("#\\/xmax")).should("have.text", String(xmax)); - cy.get(cesc("#\\/ymin")).should("have.text", String(ymin)); - cy.get(cesc("#\\/ymax")).should("have.text", String(ymax)); + cy.get(cesc("#\\/xe")).should("contain.text", "e2e3e"); + cy.get(cesc("#\\/xe")).should("contain.text", "−e−2e−3e"); + cy.get(cesc("#\\/xe")).should("contain.text", "24"); + cy.get(cesc("#\\/xe")).should("contain.text", "68"); + cy.get(cesc("#\\/xe")).should("contain.text", "−2−4−6−8"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g"].stateValues.xmin).eq(xmin); - expect(stateVariables["/g"].stateValues.xmax).eq(xmax); - expect(stateVariables["/g"].stateValues.ymin).eq(ymin); - expect(stateVariables["/g"].stateValues.ymax).eq(ymax); - }); - } + cy.get(cesc("#\\/ye")).should("contain.text", "e2e3e"); + cy.get(cesc("#\\/ye")).should("contain.text", "−e−2e−3e"); + cy.get(cesc("#\\/ye")).should("contain.text", "24"); + cy.get(cesc("#\\/ye")).should("contain.text", "68"); + cy.get(cesc("#\\/ye")).should("contain.text", "−2−4−6−8"); - let xmin = -10, - xmax = 10, - ymin = -10, - ymax = 10; + cy.get(cesc("#\\/bothe")).should("contain.text", "e2e3e"); + cy.get(cesc("#\\/bothe")).should("contain.text", "−e−2e−3e"); + cy.get(cesc("#\\/bothe")).should("not.contain.text", "24"); + cy.get(cesc("#\\/bothe")).should("not.contain.text", "68"); + cy.get(cesc("#\\/bothe")).should("not.contain.text", "−2−4−6−8"); - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 424) - .and("be.lte", 426); + cy.get(cesc("#\\/ignorebad")).should("not.contain.text", "π"); + cy.get(cesc("#\\/ignorebad")).should("not.contain.text", "e"); + cy.get(cesc("#\\/ignorebad")).should("contain.text", "68"); + cy.get(cesc("#\\/ignorebad")).should("contain.text", "−2−4−6−8"); - cy.log("set aspect ratio to 2"); - cy.get(cesc("#\\/aspectRatio") + " textarea") - .type("{end}{backspace}2{enter}", { force: true }) - .then(() => { - ymin = -5; - ymax = 5; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 212) - .and("be.lte", 213); - }); + cy.get(cesc("#\\/none_navigationbar") + " > :nth-child(1)").click(); + cy.get(cesc("#\\/xpi_navigationbar") + " > :nth-child(1)").click(); + cy.get(cesc("#\\/ypi_navigationbar") + " > :nth-child(1)").click(); + cy.get(cesc("#\\/bothpi_navigationbar") + " > :nth-child(1)").click(); + cy.get(cesc("#\\/xe_navigationbar") + " > :nth-child(1)").click(); + cy.get(cesc("#\\/ye_navigationbar") + " > :nth-child(1)").click(); + cy.get(cesc("#\\/bothe_navigationbar") + " > :nth-child(1)").click(); + cy.get( + cesc("#\\/ignorebad_navigationbar") + " > :nth-child(1)", + ).click(); - cy.log("set aspect ratio to 1/2"); - cy.get(cesc("#\\/aspectRatio") + " textarea") - .type("{end}{backspace}1/2{enter}", { force: true }) - .then(() => { - ymin = -20; - ymax = 20; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 849) - .and("be.lte", 851); - }); + cy.get(cesc("#\\/xmax")).should("have.text", "12.5"); - cy.reload(); + cy.get(cesc("#\\/none")).should("not.contain.text", "π"); + cy.get(cesc("#\\/none")).should("not.contain.text", "e"); + cy.get(cesc("#\\/none")).should("contain.text", "10"); + cy.get(cesc("#\\/none")).should("contain.text", "−10"); - cy.log("xmin alone specified"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - b -

Aspect ratio:

+ cy.get(cesc("#\\/xpi")).should("contain.text", "π2π3π"); + cy.get(cesc("#\\/xpi")).should("contain.text", "−π−2π−3π"); + cy.get(cesc("#\\/xpi")).should("contain.text", "10"); + cy.get(cesc("#\\/xpi")).should("contain.text", "−10"); - + cy.get(cesc("#\\/ypi")).should("contain.text", "π2π3π"); + cy.get(cesc("#\\/ypi")).should("contain.text", "−π−2π−3π"); + cy.get(cesc("#\\/ypi")).should("contain.text", "10"); + cy.get(cesc("#\\/ypi")).should("contain.text", "−10"); -

xmin: $g.xmin{assignNames="xmin"}

-

xmax: $g.xmax{assignNames="xmax"}

-

ymin: $g.ymin{assignNames="ymin"}

-

ymax: $g.ymax{assignNames="ymax"}

- - `, - }, - "*", - ); - }); + cy.get(cesc("#\\/bothpi")).should("contain.text", "π2π3π"); + cy.get(cesc("#\\/bothpi")).should("contain.text", "−π−2π−3π"); + cy.get(cesc("#\\/bothpi")).should("not.contain.text", "10"); + cy.get(cesc("#\\/bothpi")).should("not.contain.text", "−10"); - //wait for page to load - cy.get(cesc("#\\/_text1")) - .should("have.text", "b") - .then(() => { - xmin = -5; - xmax = 15; - ymin = -10; - ymax = 10; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 424) - .and("be.lte", 426); - }); + cy.get(cesc("#\\/xe")).should("contain.text", "e2e3e4e"); + cy.get(cesc("#\\/xe")).should("contain.text", "−e−2e"); + cy.get(cesc("#\\/xe")).should("contain.text", "−3e−4e"); + cy.get(cesc("#\\/xe")).should("contain.text", "10"); + cy.get(cesc("#\\/xe")).should("contain.text", "−10"); - cy.log("set aspect ratio to 2"); - cy.get(cesc("#\\/aspectRatio") + " textarea") - .type("{end}{backspace}2{enter}", { force: true }) - .then(() => { - ymin = -5; - ymax = 5; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 212) - .and("be.lte", 213); - }); + cy.get(cesc("#\\/ye")).should("contain.text", "e2e3e4e"); + cy.get(cesc("#\\/ye")).should("contain.text", "−e−2e"); + cy.get(cesc("#\\/ye")).should("contain.text", "−3e−4e"); + cy.get(cesc("#\\/ye")).should("contain.text", "10"); + cy.get(cesc("#\\/ye")).should("contain.text", "−10"); - cy.log("set aspect ratio to 1/2"); - cy.get(cesc("#\\/aspectRatio") + " textarea") - .type("{end}{backspace}1/2{enter}", { force: true }) - .then(() => { - ymin = -20; - ymax = 20; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 849) - .and("be.lte", 851); - }); + cy.get(cesc("#\\/bothe")).should("contain.text", "e2e3e4e"); + cy.get(cesc("#\\/bothe")).should("contain.text", "−e−2e"); + cy.get(cesc("#\\/bothe")).should("contain.text", "−3e−4e"); + cy.get(cesc("#\\/bothe")).should("not.contain.text", "10"); + cy.get(cesc("#\\/bothe")).should("not.contain.text", "−10"); - cy.reload(); + cy.get(cesc("#\\/ignorebad")).should("not.contain.text", "π"); + cy.get(cesc("#\\/ignorebad")).should("not.contain.text", "e"); + cy.get(cesc("#\\/ignorebad")).should("contain.text", "10"); + cy.get(cesc("#\\/ignorebad")).should("contain.text", "−10"); - cy.log("xmax alone specified"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - c -

Aspect ratio:

+ cy.get(cesc("#\\/none_navigationbar") + " > :nth-child(1)").click(); + cy.get(cesc("#\\/xpi_navigationbar") + " > :nth-child(1)").click(); + cy.get(cesc("#\\/ypi_navigationbar") + " > :nth-child(1)").click(); + cy.get(cesc("#\\/bothpi_navigationbar") + " > :nth-child(1)").click(); + cy.get(cesc("#\\/xe_navigationbar") + " > :nth-child(1)").click(); + cy.get(cesc("#\\/ye_navigationbar") + " > :nth-child(1)").click(); + cy.get(cesc("#\\/bothe_navigationbar") + " > :nth-child(1)").click(); + cy.get( + cesc("#\\/ignorebad_navigationbar") + " > :nth-child(1)", + ).click(); - - -

xmin: $g.xmin{assignNames="xmin"}

-

xmax: $g.xmax{assignNames="xmax"}

-

ymin: $g.ymin{assignNames="ymin"}

-

ymax: $g.ymax{assignNames="ymax"}

- - `, - }, - "*", - ); - }); - - //wait for page to load - cy.get(cesc("#\\/_text1")) - .should("have.text", "c") - .then(() => { - xmin = -15; - xmax = 5; - ymin = -10; - ymax = 10; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 424) - .and("be.lte", 426); - }); - - cy.log("set aspect ratio to 2"); - cy.get(cesc("#\\/aspectRatio") + " textarea") - .type("{end}{backspace}2{enter}", { force: true }) - .then(() => { - ymin = -5; - ymax = 5; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 212) - .and("be.lte", 213); - }); - - cy.log("set aspect ratio to 1/2"); - cy.get(cesc("#\\/aspectRatio") + " textarea") - .type("{end}{backspace}1/2{enter}", { force: true }) - .then(() => { - ymin = -20; - ymax = 20; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 849) - .and("be.lte", 851); - }); - - cy.reload(); - - cy.log("ymin alone specified"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - d -

Aspect ratio:

- - - -

xmin: $g.xmin{assignNames="xmin"}

-

xmax: $g.xmax{assignNames="xmax"}

-

ymin: $g.ymin{assignNames="ymin"}

-

ymax: $g.ymax{assignNames="ymax"}

- - `, - }, - "*", - ); - }); - - //wait for page to load - cy.get(cesc("#\\/_text1")) - .should("have.text", "d") - .then(() => { - xmin = -10; - xmax = 10; - ymin = -5; - ymax = 15; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 424) - .and("be.lte", 426); - }); - - cy.log("set aspect ratio to 2"); - cy.get(cesc("#\\/aspectRatio") + " textarea") - .type("{end}{backspace}2{enter}", { force: true }) - .then(() => { - ymax = 5; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 212) - .and("be.lte", 213); - }); - - cy.log("set aspect ratio to 1/2"); - cy.get(cesc("#\\/aspectRatio") + " textarea") - .type("{end}{backspace}1/2{enter}", { force: true }) - .then(() => { - ymax = 35; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 849) - .and("be.lte", 851); - }); - - cy.reload(); - - cy.log("ymax alone specified"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - e -

Aspect ratio:

- - - -

xmin: $g.xmin{assignNames="xmin"}

-

xmax: $g.xmax{assignNames="xmax"}

-

ymin: $g.ymin{assignNames="ymin"}

-

ymax: $g.ymax{assignNames="ymax"}

- - `, - }, - "*", - ); - }); - - //wait for page to load - cy.get(cesc("#\\/_text1")) - .should("have.text", "e") - .then(() => { - xmin = -10; - xmax = 10; - ymin = -15; - ymax = 5; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 424) - .and("be.lte", 426); - }); - - cy.log("set aspect ratio to 2"); - cy.get(cesc("#\\/aspectRatio") + " textarea") - .type("{end}{backspace}2{enter}", { force: true }) - .then(() => { - ymin = -5; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 212) - .and("be.lte", 213); - }); - - cy.log("set aspect ratio to 1/2"); - cy.get(cesc("#\\/aspectRatio") + " textarea") - .type("{end}{backspace}1/2{enter}", { force: true }) - .then(() => { - ymin = -35; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 849) - .and("be.lte", 851); - }); - - cy.reload(); - - cy.log("xmin and xmax specified"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - f -

Aspect ratio:

- - - -

xmin: $g.xmin{assignNames="xmin"}

-

xmax: $g.xmax{assignNames="xmax"}

-

ymin: $g.ymin{assignNames="ymin"}

-

ymax: $g.ymax{assignNames="ymax"}

- - `, - }, - "*", - ); - }); - - //wait for page to load - cy.get(cesc("#\\/_text1")) - .should("have.text", "f") - .then(() => { - xmin = -20; - xmax = 40; - ymin = -30; - ymax = 30; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 424) - .and("be.lte", 426); - }); - - cy.log("set aspect ratio to 2"); - cy.get(cesc("#\\/aspectRatio") + " textarea") - .type("{end}{backspace}2{enter}", { force: true }) - .then(() => { - ymin = -15; - ymax = 15; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 212) - .and("be.lte", 213); - }); - - cy.log("set aspect ratio to 1/2"); - cy.get(cesc("#\\/aspectRatio") + " textarea") - .type("{end}{backspace}1/2{enter}", { force: true }) - .then(() => { - ymin = -60; - ymax = 60; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 849) - .and("be.lte", 851); - }); - - cy.reload(); - - cy.log("ymin and ymax specified"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - g -

Aspect ratio:

- - - -

xmin: $g.xmin{assignNames="xmin"}

-

xmax: $g.xmax{assignNames="xmax"}

-

ymin: $g.ymin{assignNames="ymin"}

-

ymax: $g.ymax{assignNames="ymax"}

- - `, - }, - "*", - ); - }); - - //wait for page to load - cy.get(cesc("#\\/_text1")) - .should("have.text", "g") - .then(() => { - xmin = -30; - xmax = 30; - ymin = -20; - ymax = 40; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 424) - .and("be.lte", 426); - }); - - cy.log("set aspect ratio to 2"); - cy.get(cesc("#\\/aspectRatio") + " textarea") - .type("{end}{backspace}2{enter}", { force: true }) - .then(() => { - xmin = -60; - xmax = 60; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 212) - .and("be.lte", 213); - }); - - cy.log("set aspect ratio to 1/2"); - cy.get(cesc("#\\/aspectRatio") + " textarea") - .type("{end}{backspace}1/2{enter}", { force: true }) - .then(() => { - xmin = -15; - xmax = 15; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 849) - .and("be.lte", 851); - }); - - cy.reload(); - - cy.log("xmin, xmax, ymin and ymax specified"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - h -

Aspect ratio:

- - - -

xmin: $g.xmin{assignNames="xmin"}

-

xmax: $g.xmax{assignNames="xmax"}

-

ymin: $g.ymin{assignNames="ymin"}

-

ymax: $g.ymax{assignNames="ymax"}

- - `, - }, - "*", - ); - }); - - //wait for page to load - cy.get(cesc("#\\/_text1")) - .should("have.text", "h") - .then(() => { - xmin = -50; - xmax = 30; - ymin = -20; - ymax = 60; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 424) - .and("be.lte", 426); - }); - - cy.log("set aspect ratio to 2"); - cy.get(cesc("#\\/aspectRatio") + " textarea") - .type("{end}{backspace}2{enter}", { force: true }) - .then(() => { - xmax = 70; - ymax = 40; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 212) - .and("be.lte", 213); - }); - - cy.log("set aspect ratio to 1/2"); - cy.get(cesc("#\\/aspectRatio") + " textarea") - .type("{end}{backspace}1/2{enter}", { force: true }) - .then(() => { - xmax = 30; - ymax = 140; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 849) - .and("be.lte", 851); - }); - - cy.reload(); - - cy.log("leave out xmin"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - i -

Aspect ratio:

- - - -

xmin: $g.xmin{assignNames="xmin"}

-

xmax: $g.xmax{assignNames="xmax"}

-

ymin: $g.ymin{assignNames="ymin"}

-

ymax: $g.ymax{assignNames="ymax"}

- - `, - }, - "*", - ); - }); - - //wait for page to load - cy.get(cesc("#\\/_text1")) - .should("have.text", "i") - .then(() => { - xmin = -30; - xmax = 30; - ymin = -20; - ymax = 40; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 424) - .and("be.lte", 426); - }); - - cy.log("set aspect ratio to 2"); - cy.get(cesc("#\\/aspectRatio") + " textarea") - .type("{end}{backspace}2{enter}", { force: true }) - .then(() => { - xmin = -90; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 212) - .and("be.lte", 213); - }); - - cy.log("set aspect ratio to 1/2"); - cy.get(cesc("#\\/aspectRatio") + " textarea") - .type("{end}{backspace}1/2{enter}", { force: true }) - .then(() => { - xmin = 0; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 849) - .and("be.lte", 851); - }); - - cy.reload(); - - cy.log("leave out xmax"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - j -

Aspect ratio:

- - - -

xmin: $g.xmin{assignNames="xmin"}

-

xmax: $g.xmax{assignNames="xmax"}

-

ymin: $g.ymin{assignNames="ymin"}

-

ymax: $g.ymax{assignNames="ymax"}

- - `, - }, - "*", - ); - }); - - //wait for page to load - cy.get(cesc("#\\/_text1")) - .should("have.text", "j") - .then(() => { - xmin = -30; - xmax = 30; - ymin = -20; - ymax = 40; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 424) - .and("be.lte", 426); - }); - - cy.log("set aspect ratio to 2"); - cy.get(cesc("#\\/aspectRatio") + " textarea") - .type("{end}{backspace}2{enter}", { force: true }) - .then(() => { - xmax = 90; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 212) - .and("be.lte", 213); - }); - - cy.log("set aspect ratio to 1/2"); - cy.get(cesc("#\\/aspectRatio") + " textarea") - .type("{end}{backspace}1/2{enter}", { force: true }) - .then(() => { - xmax = 0; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 849) - .and("be.lte", 851); - }); - - cy.reload(); - - cy.log("leave out ymin"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - k -

Aspect ratio:

- - - -

xmin: $g.xmin{assignNames="xmin"}

-

xmax: $g.xmax{assignNames="xmax"}

-

ymin: $g.ymin{assignNames="ymin"}

-

ymax: $g.ymax{assignNames="ymax"}

- - `, - }, - "*", - ); - }); - - //wait for page to load - cy.get(cesc("#\\/_text1")) - .should("have.text", "k") - .then(() => { - xmin = -50; - xmax = 30; - ymin = -40; - ymax = 40; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 424) - .and("be.lte", 426); - }); - - cy.log("set aspect ratio to 2"); - cy.get(cesc("#\\/aspectRatio") + " textarea") - .type("{end}{backspace}2{enter}", { force: true }) - .then(() => { - ymin = 0; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 212) - .and("be.lte", 213); - }); - - cy.log("set aspect ratio to 1/2"); - cy.get(cesc("#\\/aspectRatio") + " textarea") - .type("{end}{backspace}1/2{enter}", { force: true }) - .then(() => { - ymin = -120; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 849) - .and("be.lte", 851); - }); - - cy.reload(); - - cy.log("leave out ymax"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - l -

Aspect ratio:

- - - -

xmin: $g.xmin{assignNames="xmin"}

-

xmax: $g.xmax{assignNames="xmax"}

-

ymin: $g.ymin{assignNames="ymin"}

-

ymax: $g.ymax{assignNames="ymax"}

- - `, - }, - "*", - ); - }); - - //wait for page to load - cy.get(cesc("#\\/_text1")) - .should("have.text", "l") - .then(() => { - xmin = -50; - xmax = 30; - ymin = -40; - ymax = 40; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 424) - .and("be.lte", 426); - }); - - cy.log("set aspect ratio to 2"); - cy.get(cesc("#\\/aspectRatio") + " textarea") - .type("{end}{backspace}2{enter}", { force: true }) - .then(() => { - ymax = 0; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 212) - .and("be.lte", 213); - }); - - cy.log("set aspect ratio to 1/2"); - cy.get(cesc("#\\/aspectRatio") + " textarea") - .type("{end}{backspace}1/2{enter}", { force: true }) - .then(() => { - ymax = 120; - checkLimits(xmin, xmax, ymin, ymax); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 849) - .and("be.lte", 851); - }); - }); - - it("identical axis scales, without given aspect ratio", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - -

xmin: $g.xmin{assignNames="xmin"}

-

xmax: $g.xmax{assignNames="xmax"}

-

ymin: $g.ymin{assignNames="ymin"}

-

ymax: $g.ymax{assignNames="ymax"}

- -

Change xmin:

-

Change xmax:

-

Change ymin:

-

Change ymax:

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - function checkLimits(xmin, xmax, ymin, ymax) { - cy.get(cesc("#\\/xmin")).should("have.text", String(xmin)); - cy.get(cesc("#\\/xmax")).should("have.text", String(xmax)); - cy.get(cesc("#\\/ymin")).should("have.text", String(ymin)); - cy.get(cesc("#\\/ymax")).should("have.text", String(ymax)); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g"].stateValues.xmin).eq(xmin); - expect(stateVariables["/g"].stateValues.xmax).eq(xmax); - expect(stateVariables["/g"].stateValues.ymin).eq(ymin); - expect(stateVariables["/g"].stateValues.ymax).eq(ymax); - }); - } - - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 424) - .and("be.lte", 426); - - checkLimits(-10, 10, -10, 10); - - cy.log("set xmin to -5"); - cy.get(cesc("#\\/xminInput") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}-5{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/xmin")).should("have.text", "-5"); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 566) - .and("be.lte", 567); - - checkLimits(-5, 10, -10, 10); - - cy.log("set ymax to 0"); - cy.get(cesc("#\\/ymaxInput") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}0{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/ymax")).should("have.text", "0"); - cy.get(cesc("#\\/g")) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", 424) - .and("be.lte", 426); - cy.get(cesc("#\\/g")) - .invoke("css", "height") - .then((height) => parseInt(height)) - .should("be.gte", 283) - .and("be.lte", 284); - - checkLimits(-5, 10, -10, 0); - }); - - it("show grid", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - -

Graph 1 has grid: $g1.grid{assignNames="sg1"}

- - - -

Graph 2 has grid: $g2.grid{assignNames="sg2"}

- - - -

Graph 3 has grid: $g3.grid{assignNames="sg3"}

- - - -

Graph 4 has grid: $g4.grid{assignNames="sg4"}

- - - -

Graph 5 has grid: $g5.grid{assignNames="sg5"}

- - -

Show grid:

- - -

Graph 6 has grid: $g6.grid{assignNames="sg6"}

- - -

Show grid:

- - -

Graph 7 has grid: $g7.grid{assignNames="sg7"}

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - // not sure what to test as don't know how to check renderer... - cy.get(cesc("#\\/sg1")).should("have.text", "none"); - cy.get(cesc("#\\/sg2")).should("have.text", "none"); - cy.get(cesc("#\\/sg3")).should("have.text", "medium"); - cy.get(cesc("#\\/sg4")).should("have.text", "medium"); - cy.get(cesc("#\\/sg5")).should("have.text", "dense"); - cy.get(cesc("#\\/sg6")).should("have.text", "none"); - cy.get(cesc("#\\/sg7")).should("have.text", "none"); - - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/sg6")).should("have.text", "medium"); - - cy.get(cesc("#\\/ti_input")).type("true{enter}"); - cy.get(cesc("#\\/sg7")).should("have.text", "medium"); - - cy.get(cesc("#\\/ti_input")).clear().type("false{enter}"); - cy.get(cesc("#\\/sg7")).should("have.text", "none"); - - cy.get(cesc("#\\/ti_input")).clear().type("dense{enter}"); - cy.get(cesc("#\\/sg7")).should("have.text", "dense"); - - cy.get(cesc("#\\/ti_input")).clear().type("hello{enter}"); - cy.get(cesc("#\\/sg7")).should("have.text", "none"); - - cy.get(cesc("#\\/ti_input")).clear().type("medium{enter}"); - cy.get(cesc("#\\/sg7")).should("have.text", "medium"); - - cy.get(cesc("#\\/ti_input")).clear().type("none{enter}"); - cy.get(cesc("#\\/sg7")).should("have.text", "none"); - }); - - it("fixed grids", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - -

Graph 1 has grid: $g1.grid{assignNames="sg1"}

- -

grid x:

-

grid y:

- - -

Graph 2 has grid: $g2.grid{assignNames="sg2"}

- -

grid x: $g3x

-

grid y: $g3y

- - -

Graph 3 has grid: $g3.grid{assignNames="sg3"}

- -

grid x:

-

grid y:

- - -

Graph 4 has grid: $g4.grid{assignNames="sg4"}

- -

grid x: $g5x

-

grid y: $g5y

- - -

Graph 5 has grid: $g5.grid{assignNames="sg5"}

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/sg1")).should("have.text", "1, 1.571"); - cy.get(cesc("#\\/sg2")).should("have.text", "none"); - cy.get(cesc("#\\/sg3")).should("have.text", "none"); - cy.get(cesc("#\\/sg4")).should("have.text", "2, 3"); - cy.get(cesc("#\\/sg5")).should("have.text", "2, 3"); - - cy.get(cesc("#\\/g2x") + " textarea").type("3", { force: true }); - cy.get(cesc("#\\/g2y") + " textarea") - .type("1.5", { force: true }) - .blur(); - cy.get(cesc("#\\/sg2")).should("have.text", "3, 1.5"); - - cy.get(cesc("#\\/g3x") + " textarea").type("3", { force: true }); - cy.get(cesc("#\\/g3y") + " textarea") - .type("1.5", { force: true }) - .blur(); - cy.get(cesc("#\\/sg3")).should("have.text", "3, 1.5"); - - cy.get(cesc("#\\/g4x") + " textarea").type("{end}{backspace}3", { - force: true, - }); - cy.get(cesc("#\\/g4y") + " textarea") - .type("{end}.5", { force: true }) - .blur(); - cy.get(cesc("#\\/sg4")).should("have.text", "6, 4.5"); - - cy.get(cesc("#\\/g5x") + " textarea").type("{end}{backspace}3", { - force: true, - }); - cy.get(cesc("#\\/g5y") + " textarea") - .type("{end}.5", { force: true }) - .blur(); - cy.get(cesc("#\\/sg5")).should("have.text", "6, 4.5"); - - cy.get(cesc("#\\/g2x") + " textarea").type("{end}e/2", { force: true }); - cy.get(cesc("#\\/g2y") + " textarea") - .type("{end}pi", { force: true }) - .blur(); - cy.get(cesc("#\\/sg2")).should("have.text", "4.08, 4.71"); - - cy.get(cesc("#\\/g3x") + " textarea").type("{end}e/2", { force: true }); - cy.get(cesc("#\\/g3y") + " textarea") - .type("{end}pi", { force: true }) - .blur(); - cy.get(cesc("#\\/sg3")).should("have.text", "4.08, 4.71"); - - cy.get(cesc("#\\/g4x") + " textarea").type("{end}pi/5", { - force: true, - }); - cy.get(cesc("#\\/g4y") + " textarea") - .type("{end}e/6", { force: true }) - .blur(); - cy.get(cesc("#\\/sg4")).should("have.text", "3.77, 2.04"); - - cy.get(cesc("#\\/g5x") + " textarea").type("{end}pi/5", { - force: true, - }); - cy.get(cesc("#\\/g5y") + " textarea") - .type("{end}e/6", { force: true }) - .blur(); - cy.get(cesc("#\\/sg5")).should("have.text", "3.77, 2.04"); - }); - - // check for bug in placeholder adapter - it("graph with label as submitted response, createComponentOfType specified", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - $(x.submittedResponse{ createComponentOfType='math'}) - y - - - x - $x.submittedResponse{assignNames="sr"} - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - // not sure what to test as don't know how to check renderer... - // but main thing is that don't have an error - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_graph1"].stateValues.xlabel).eq( - "\\(\uff3f\\)", - ); - - let mathinputName = - stateVariables["/x"].stateValues.inputChildren[0].componentName; - let mathinputAnchor = cesc2("#" + mathinputName) + " textarea"; - - cy.get(mathinputAnchor).type("x{enter}", { force: true }); - - cy.get(cesc("#\\/sr") + " .mjx-mrow").should("contain.text", "x"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_graph1"].stateValues.xlabel).eq( - "\\(x\\)", - ); - }); - }); - }); - - it("display tick labels", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - $_graph1.displayXAxisTickLabels{assignNames="b1a"} - - $_graph1.displayYAxisTickLabels{assignNames="b2a"} - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - // not sure what to test as don't know how to check renderer... - cy.get(cesc("#\\/b1a")).should("have.text", "false"); - cy.get(cesc("#\\/b2a")).should("have.text", "true"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_graph1"].stateValues.displayXAxisTickLabels, - ).eq(false); - expect( - stateVariables["/_graph1"].stateValues.displayYAxisTickLabels, - ).eq(true); - }); - - cy.get(cesc("#\\/b1")).click(); - - cy.get(cesc("#\\/b1a")).should("have.text", "true"); - cy.get(cesc("#\\/b2a")).should("have.text", "true"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_graph1"].stateValues.displayXAxisTickLabels, - ).eq(true); - expect( - stateVariables["/_graph1"].stateValues.displayYAxisTickLabels, - ).eq(true); - }); - - cy.get(cesc("#\\/b2")).click(); - - cy.get(cesc("#\\/b1a")).should("have.text", "true"); - cy.get(cesc("#\\/b2a")).should("have.text", "false"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_graph1"].stateValues.displayXAxisTickLabels, - ).eq(true); - expect( - stateVariables["/_graph1"].stateValues.displayYAxisTickLabels, - ).eq(false); - }); - - cy.get(cesc("#\\/b1")).click(); - - cy.get(cesc("#\\/b1a")).should("have.text", "false"); - cy.get(cesc("#\\/b2a")).should("have.text", "false"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_graph1"].stateValues.displayXAxisTickLabels, - ).eq(false); - expect( - stateVariables["/_graph1"].stateValues.displayYAxisTickLabels, - ).eq(false); - }); - - cy.get(cesc("#\\/b2")).click(); - - cy.get(cesc("#\\/b1a")).should("have.text", "false"); - cy.get(cesc("#\\/b2a")).should("have.text", "true"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_graph1"].stateValues.displayXAxisTickLabels, - ).eq(false); - expect( - stateVariables["/_graph1"].stateValues.displayYAxisTickLabels, - ).eq(true); - }); - }); - - it("graph sizes", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let expectedSizes = { - g: "medium", - gtiny: "tiny", - gsmall: "small", - gmedium: "medium", - glarge: "large", - gfull: "full", - ginvalid: "medium", - ga10: "tiny", - ga100: "tiny", - ga200: "small", - ga300: "small", - ga400: "medium", - ga500: "medium", - ga600: "large", - ga700: "large", - ga800: "full", - ga900: "full", - ga10000: "full", - gp1: "tiny", - gp10: "tiny", - gp20: "small", - gp30: "small", - gp40: "small", - gp50: "medium", - gp60: "medium", - gp70: "large", - gp80: "large", - gp90: "full", - gp100: "full", - gp1000: "full", - gbadwidth: "medium", - }; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let name in expectedSizes) { - expect(stateVariables["/" + name].stateValues.size).eq( - expectedSizes[name], - ); - } - }); - - for (let name in expectedSizes) { - cy.get(cesc2("#/" + name)) - .invoke("css", "width") - .then((width) => parseInt(width)) - .should("be.gte", widthsBySize[expectedSizes[name]] - 4) - .and("be.lte", widthsBySize[expectedSizes[name]] + 1); - } - }); - - it("horizontal align", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g"].stateValues.horizontalAlign).eq( - "center", - ); - expect(stateVariables["/gleft"].stateValues.horizontalAlign).eq( - "left", - ); - expect(stateVariables["/gright"].stateValues.horizontalAlign).eq( - "right", - ); - expect(stateVariables["/gcenter"].stateValues.horizontalAlign).eq( - "center", - ); - expect(stateVariables["/ginvalid"].stateValues.horizontalAlign).eq( - "center", - ); - }); - - // TODO: anything to check in the DOM? - }); - - it("displayMode", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g"].stateValues.displayMode).eq("block"); - expect(stateVariables["/ginline"].stateValues.displayMode).eq( - "inline", - ); - expect(stateVariables["/gblock"].stateValues.displayMode).eq( - "block", - ); - expect(stateVariables["/ginvalid"].stateValues.displayMode).eq( - "block", - ); - }); - - // TODO: anything to check in the DOM? - }); - - it("tick scale factor", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - - - - - - $ignorebad.xmin{assignNames="xmin"} - $ignorebad.xmax{assignNames="xmax"} - $ignorebad.ymin{assignNames="ymin"} - $ignorebad.ymax{assignNames="ymax"} - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - // Note: these are brittle tests and could start failing if internals of jsxgraph changes - - cy.get(cesc("#\\/none")).should("not.contain.text", "π"); - cy.get(cesc("#\\/none")).should("not.contain.text", "e"); - cy.get(cesc("#\\/none")).should("contain.text", "68"); - cy.get(cesc("#\\/none")).should("contain.text", "−2−4−6−8"); - - cy.get(cesc("#\\/xpi")).should("contain.text", "π2π3π"); - cy.get(cesc("#\\/xpi")).should("contain.text", "−π−2π−3π"); - cy.get(cesc("#\\/xpi")).should("contain.text", "24"); - cy.get(cesc("#\\/xpi")).should("contain.text", "68"); - cy.get(cesc("#\\/xpi")).should("contain.text", "−2−4−6−8"); - - cy.get(cesc("#\\/ypi")).should("contain.text", "π2π3π"); - cy.get(cesc("#\\/ypi")).should("contain.text", "−π−2π−3π"); - cy.get(cesc("#\\/ypi")).should("contain.text", "24"); - cy.get(cesc("#\\/ypi")).should("contain.text", "68"); - cy.get(cesc("#\\/ypi")).should("contain.text", "−2−4−6−8"); - - cy.get(cesc("#\\/bothpi")).should("contain.text", "π2π3π"); - cy.get(cesc("#\\/bothpi")).should("contain.text", "−π−2π−3π"); - cy.get(cesc("#\\/bothpi")).should("not.contain.text", "24"); - cy.get(cesc("#\\/bothpi")).should("not.contain.text", "68"); - cy.get(cesc("#\\/bothpi")).should("not.contain.text", "−2−4−6−8"); - - cy.get(cesc("#\\/xe")).should("contain.text", "e2e3e"); - cy.get(cesc("#\\/xe")).should("contain.text", "−e−2e−3e"); - cy.get(cesc("#\\/xe")).should("contain.text", "24"); - cy.get(cesc("#\\/xe")).should("contain.text", "68"); - cy.get(cesc("#\\/xe")).should("contain.text", "−2−4−6−8"); - - cy.get(cesc("#\\/ye")).should("contain.text", "e2e3e"); - cy.get(cesc("#\\/ye")).should("contain.text", "−e−2e−3e"); - cy.get(cesc("#\\/ye")).should("contain.text", "24"); - cy.get(cesc("#\\/ye")).should("contain.text", "68"); - cy.get(cesc("#\\/ye")).should("contain.text", "−2−4−6−8"); - - cy.get(cesc("#\\/bothe")).should("contain.text", "e2e3e"); - cy.get(cesc("#\\/bothe")).should("contain.text", "−e−2e−3e"); - cy.get(cesc("#\\/bothe")).should("not.contain.text", "24"); - cy.get(cesc("#\\/bothe")).should("not.contain.text", "68"); - cy.get(cesc("#\\/bothe")).should("not.contain.text", "−2−4−6−8"); - - cy.get(cesc("#\\/ignorebad")).should("not.contain.text", "π"); - cy.get(cesc("#\\/ignorebad")).should("not.contain.text", "e"); - cy.get(cesc("#\\/ignorebad")).should("contain.text", "68"); - cy.get(cesc("#\\/ignorebad")).should("contain.text", "−2−4−6−8"); - - cy.get(cesc("#\\/none_navigationbar") + " > :nth-child(1)").click(); - cy.get(cesc("#\\/xpi_navigationbar") + " > :nth-child(1)").click(); - cy.get(cesc("#\\/ypi_navigationbar") + " > :nth-child(1)").click(); - cy.get(cesc("#\\/bothpi_navigationbar") + " > :nth-child(1)").click(); - cy.get(cesc("#\\/xe_navigationbar") + " > :nth-child(1)").click(); - cy.get(cesc("#\\/ye_navigationbar") + " > :nth-child(1)").click(); - cy.get(cesc("#\\/bothe_navigationbar") + " > :nth-child(1)").click(); - cy.get( - cesc("#\\/ignorebad_navigationbar") + " > :nth-child(1)", - ).click(); - - cy.get(cesc("#\\/xmax")).should("have.text", "12.5"); - - cy.get(cesc("#\\/none")).should("not.contain.text", "π"); - cy.get(cesc("#\\/none")).should("not.contain.text", "e"); - cy.get(cesc("#\\/none")).should("contain.text", "10"); - cy.get(cesc("#\\/none")).should("contain.text", "−10"); - - cy.get(cesc("#\\/xpi")).should("contain.text", "π2π3π"); - cy.get(cesc("#\\/xpi")).should("contain.text", "−π−2π−3π"); - cy.get(cesc("#\\/xpi")).should("contain.text", "10"); - cy.get(cesc("#\\/xpi")).should("contain.text", "−10"); - - cy.get(cesc("#\\/ypi")).should("contain.text", "π2π3π"); - cy.get(cesc("#\\/ypi")).should("contain.text", "−π−2π−3π"); - cy.get(cesc("#\\/ypi")).should("contain.text", "10"); - cy.get(cesc("#\\/ypi")).should("contain.text", "−10"); - - cy.get(cesc("#\\/bothpi")).should("contain.text", "π2π3π"); - cy.get(cesc("#\\/bothpi")).should("contain.text", "−π−2π−3π"); - cy.get(cesc("#\\/bothpi")).should("not.contain.text", "10"); - cy.get(cesc("#\\/bothpi")).should("not.contain.text", "−10"); - - cy.get(cesc("#\\/xe")).should("contain.text", "e2e3e4e"); - cy.get(cesc("#\\/xe")).should("contain.text", "−e−2e"); - cy.get(cesc("#\\/xe")).should("contain.text", "−3e−4e"); - cy.get(cesc("#\\/xe")).should("contain.text", "10"); - cy.get(cesc("#\\/xe")).should("contain.text", "−10"); - - cy.get(cesc("#\\/ye")).should("contain.text", "e2e3e4e"); - cy.get(cesc("#\\/ye")).should("contain.text", "−e−2e"); - cy.get(cesc("#\\/ye")).should("contain.text", "−3e−4e"); - cy.get(cesc("#\\/ye")).should("contain.text", "10"); - cy.get(cesc("#\\/ye")).should("contain.text", "−10"); - - cy.get(cesc("#\\/bothe")).should("contain.text", "e2e3e4e"); - cy.get(cesc("#\\/bothe")).should("contain.text", "−e−2e"); - cy.get(cesc("#\\/bothe")).should("contain.text", "−3e−4e"); - cy.get(cesc("#\\/bothe")).should("not.contain.text", "10"); - cy.get(cesc("#\\/bothe")).should("not.contain.text", "−10"); - - cy.get(cesc("#\\/ignorebad")).should("not.contain.text", "π"); - cy.get(cesc("#\\/ignorebad")).should("not.contain.text", "e"); - cy.get(cesc("#\\/ignorebad")).should("contain.text", "10"); - cy.get(cesc("#\\/ignorebad")).should("contain.text", "−10"); - - cy.get(cesc("#\\/none_navigationbar") + " > :nth-child(1)").click(); - cy.get(cesc("#\\/xpi_navigationbar") + " > :nth-child(1)").click(); - cy.get(cesc("#\\/ypi_navigationbar") + " > :nth-child(1)").click(); - cy.get(cesc("#\\/bothpi_navigationbar") + " > :nth-child(1)").click(); - cy.get(cesc("#\\/xe_navigationbar") + " > :nth-child(1)").click(); - cy.get(cesc("#\\/ye_navigationbar") + " > :nth-child(1)").click(); - cy.get(cesc("#\\/bothe_navigationbar") + " > :nth-child(1)").click(); - cy.get( - cesc("#\\/ignorebad_navigationbar") + " > :nth-child(1)", - ).click(); - - cy.get(cesc("#\\/xmax")).should("have.text", "15.625"); + cy.get(cesc("#\\/xmax")).should("have.text", "15.625"); cy.get(cesc("#\\/none")).should("not.contain.text", "π"); cy.get(cesc("#\\/none")).should("not.contain.text", "e"); @@ -2221,328 +391,4 @@ describe("Graph Tag Tests", function () { cy.get(cesc("#\\/ignorebad")).should("contain.text", "10"); cy.get(cesc("#\\/ignorebad")).should("contain.text", "−10"); }); - - it("display axes", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - $_graph1.displayXAxis{assignNames="b1a"} - - $_graph1.displayYAxis{assignNames="b2a"} - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - // not sure what to test as don't know how to check renderer... - cy.get(cesc("#\\/b1a")).should("have.text", "false"); - cy.get(cesc("#\\/b2a")).should("have.text", "true"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_graph1"].stateValues.displayXAxis).eq( - false, - ); - expect(stateVariables["/_graph1"].stateValues.displayYAxis).eq( - true, - ); - }); - - cy.get(cesc("#\\/b1")).click(); - - cy.get(cesc("#\\/b1a")).should("have.text", "true"); - cy.get(cesc("#\\/b2a")).should("have.text", "true"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_graph1"].stateValues.displayXAxis).eq( - true, - ); - expect(stateVariables["/_graph1"].stateValues.displayYAxis).eq( - true, - ); - }); - - cy.get(cesc("#\\/b2")).click(); - - cy.get(cesc("#\\/b1a")).should("have.text", "true"); - cy.get(cesc("#\\/b2a")).should("have.text", "false"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_graph1"].stateValues.displayXAxis).eq( - true, - ); - expect(stateVariables["/_graph1"].stateValues.displayYAxis).eq( - false, - ); - }); - - cy.get(cesc("#\\/b1")).click(); - - cy.get(cesc("#\\/b1a")).should("have.text", "false"); - cy.get(cesc("#\\/b2a")).should("have.text", "false"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_graph1"].stateValues.displayXAxis).eq( - false, - ); - expect(stateVariables["/_graph1"].stateValues.displayYAxis).eq( - false, - ); - }); - - cy.get(cesc("#\\/b2")).click(); - - cy.get(cesc("#\\/b1a")).should("have.text", "false"); - cy.get(cesc("#\\/b2a")).should("have.text", "true"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_graph1"].stateValues.displayXAxis).eq( - false, - ); - expect(stateVariables["/_graph1"].stateValues.displayYAxis).eq( - true, - ); - }); - }); - - it("display navigation bar", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - $_graph1.showNavigation{assignNames="ba"} - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - // not sure what to test as don't know how to check renderer... - cy.get(cesc("#\\/ba")).should("have.text", "false"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_graph1"].stateValues.showNavigation).eq( - false, - ); - }); - - cy.get(cesc("#\\/b")).click(); - - cy.get(cesc("#\\/ba")).should("have.text", "true"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_graph1"].stateValues.showNavigation).eq( - true, - ); - }); - - cy.get(cesc("#\\/b")).click(); - - cy.get(cesc("#\\/ba")).should("have.text", "false"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_graph1"].stateValues.showNavigation).eq( - false, - ); - }); - }); - - it("display digits and decimals, overwrite in copies", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - -

$g.xmin, $g.xmax, $g.ymin, $g.ymax

- -

$gdg3.xmin, $gdg3.xmax, $gdg3.ymin, $gdg3.ymax

-

$gdg3a.xmin, $gdg3a.xmax, $gdg3a.ymin, $gdg3a.ymax

-

$gdg3b.xmin, $gdg3b.xmax, $gdg3b.ymin, $gdg3b.ymax

-

$g{displayDigits="5"}.xmin, $g{displayDigits="5"}.xmax, $g{displayDigits="5"}.ymin, $g{displayDigits="5"}.ymax

-

$gdc5{displayDigits="5"}.xmin, $gdc5{displayDigits="5"}.xmax, $gdc5{displayDigits="5"}.ymin, $gdc5{displayDigits="5"}.ymax

- -

$gdc5.xmin, $gdc5.xmax, $gdc5.ymin, $gdc5.ymax

-

$gdc5a.xmin, $gdc5a.xmax, $gdc5a.ymin, $gdc5a.ymax

-

$gdc5b.xmin, $gdc5b.xmax, $gdc5b.ymin, $gdc5b.ymax

-

$g{displayDecimals="5"}.xmin, $g{displayDecimals="5"}.xmax, $g{displayDecimals="5"}.ymin, $g{displayDecimals="5"}.ymax

-

$gdg3{displayDecimals="5"}.xmin, $gdg3{displayDecimals="5"}.xmax, $gdg3{displayDecimals="5"}.ymin, $gdg3{displayDecimals="5"}.ymax

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/p")).should("have.text", "-45.03, 8.29, -5.58, 7.84"); - cy.get(cesc("#\\/pdg3")).should( - "have.text", - "-45.032, 8.2857, -5.5823, 7.8371", - ); - cy.get(cesc("#\\/pdg3b")).should( - "have.text", - "-45.032, 8.2857, -5.5823, 7.8371", - ); - cy.get(cesc("#\\/pdg3c")).should( - "have.text", - "-45.032, 8.2857, -5.5823, 7.8371", - ); - cy.get(cesc("#\\/pdg3d")).should( - "have.text", - "-45.032, 8.2857, -5.5823, 7.8371", - ); - cy.get(cesc("#\\/pdc5")).should( - "have.text", - "-45.03233, 8.28572, -5.58234, 7.8371", - ); - cy.get(cesc("#\\/pdc5b")).should( - "have.text", - "-45.03233, 8.28572, -5.58234, 7.8371", - ); - cy.get(cesc("#\\/pdc5c")).should( - "have.text", - "-45.03233, 8.28572, -5.58234, 7.8371", - ); - cy.get(cesc("#\\/pdc5d")).should( - "have.text", - "-45.03233, 8.28572, -5.58234, 7.8371", - ); - }); - - it("pegboard", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - // not sure what to test as don't know how to check renderer... - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_pegboard1"].stateValues.dx).eq(1); - expect(stateVariables["/_pegboard1"].stateValues.dy).eq(1); - expect(stateVariables["/_pegboard1"].stateValues.xoffset).eq(0); - expect(stateVariables["/_pegboard1"].stateValues.yoffset).eq(0); - expect(stateVariables["/_pegboard2"].stateValues.dx).eq(3); - expect(stateVariables["/_pegboard2"].stateValues.dy).eq(2); - expect(stateVariables["/_pegboard2"].stateValues.xoffset).eq(1); - expect(stateVariables["/_pegboard2"].stateValues.yoffset).eq(-1); - }); - }); - - it("show border", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - // not sure what to test as don't know how to check renderer... - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_graph1"].stateValues.showBorder).eq(true); - expect(stateVariables["/_graph2"].stateValues.showBorder).eq(true); - expect(stateVariables["/_graph3"].stateValues.showBorder).eq(false); - }); - }); - - it("graph inside graph renders children in parent graph", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (4,-5) - - (6,9) - - - - - - - - - $g1 - - - `, - }, - "*", - ); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - // Not sure what to test as the interesting part is the graph renderer - // The only new part from core is that the inner graph ignores its xmin, etc. attributes - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/g1inner"].stateValues.xmin).eq(-10); - expect(stateVariables["/g1inner"].stateValues.xmax).eq(10); - expect(stateVariables["/g1inner"].stateValues.ymin).eq(-10); - expect(stateVariables["/g1inner"].stateValues.ymax).eq(10); - }); - }); - }); }); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/map.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/map.cy.js index 82b5d0d33..ae280781d 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/map.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/map.cy.js @@ -1,5530 +1,9 @@ -import { cesc, cesc2 } from "@doenet/utils"; +import { cesc2 } from "@doenet/utils"; -function nInDOM(n) { - if (n < 0) { - return `−${Math.abs(n)}`; - } else { - return String(n); - } -} - -describe("Map Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("single map of maths", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - x - y - - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let replacements = stateVariables["/_map1"].replacements; - let mathr1Name = - stateVariables[replacements[0].componentName].replacements[0] - .componentName; - let mathr1Anchor = "#" + mathr1Name; - let mathr2Name = - stateVariables[replacements[1].componentName].replacements[0] - .componentName; - let mathr2Anchor = "#" + mathr2Name; - - cy.log("Test values displayed in browser"); - cy.get(`${cesc2(mathr1Anchor)} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(2x)+1"); - }); - cy.get(`${cesc2(mathr2Anchor)} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(2y)+2"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(() => { - expect(stateVariables[mathr1Name].stateValues.value).eqls([ - "+", - ["apply", "sin", ["*", 2, "x"]], - 1, - ]); - expect(stateVariables[mathr2Name].stateValues.value).eqls([ - "+", - ["apply", "sin", ["*", 2, "y"]], - 2, - ]); - }); - }); - }); - - it("single map of texts", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - squirrelbat - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait for page to load - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let replacements = stateVariables["/_map1"].replacements; - let textr1Name = - stateVariables[replacements[0].componentName].replacements[0] - .componentName; - let textr1Anchor = "#" + textr1Name; - let textr2Name = - stateVariables[replacements[1].componentName].replacements[0] - .componentName; - let textr2Anchor = "#" + textr2Name; - - cy.log("Test values displayed in browser"); - cy.get(cesc2(textr1Anchor)).should( - "have.text", - "You are a squirrel!", - ); - cy.get(cesc2(textr2Anchor)).should("have.text", "You are a bat!"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(() => { - expect(stateVariables[textr1Name].stateValues.value).eq( - "You are a squirrel!", - ); - }); - }); - }); - - it("single map of sequence", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let replacements = stateVariables["/_map1"].replacements; - let mathrNames = replacements.map( - (x) => - stateVariables[x.componentName].replacements[0] - .componentName, - ); - let mathrAnchors = mathrNames.map((x) => cesc2("#" + x)); - - cy.log("Test values displayed in browser"); - cy.get(`${mathrAnchors[0]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(`${mathrAnchors[1]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(`${mathrAnchors[2]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9"); - }); - cy.get(`${mathrAnchors[3]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("16"); - }); - cy.get(`${mathrAnchors[4]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("25"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(() => { - expect(stateVariables[mathrNames[0]].stateValues.value).eq(1); - expect(stateVariables[mathrNames[1]].stateValues.value).eq(4); - expect(stateVariables[mathrNames[2]].stateValues.value).eq(9); - expect(stateVariables[mathrNames[3]].stateValues.value).eq(16); - expect(stateVariables[mathrNames[4]].stateValues.value).eq(25); - }); - }); - }); - - it("triple parallel map", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let replacements = stateVariables["/_map1"].replacements; - let mathrNames = replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements.map( - (x) => x.componentName, - ), - ], - [], - ); - let mathrAnchors = mathrNames.map((x) => cesc2("#" + x)); - - cy.log("Test values displayed in browser"); - cy.get(`${mathrAnchors[0]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,21,−5)"); - }); - cy.get(`${mathrAnchors[1]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1,1)"); - }); - cy.get(`${mathrAnchors[2]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,22,−8)"); - }); - cy.get(`${mathrAnchors[3]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,2,2)"); - }); - cy.get(`${mathrAnchors[4]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,23,−11)"); - }); - cy.get(`${mathrAnchors[5]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,3,3)"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(() => { - expect(stateVariables[mathrNames[0]].stateValues.value).eqls([ - "tuple", - 1, - 21, - -5, - ]); - expect(stateVariables[mathrNames[1]].stateValues.value).eqls([ - "tuple", - 1, - 1, - 1, - ]); - expect(stateVariables[mathrNames[2]].stateValues.value).eqls([ - "tuple", - 2, - 22, - -8, - ]); - expect(stateVariables[mathrNames[3]].stateValues.value).eqls([ - "tuple", - 2, - 2, - 2, - ]); - expect(stateVariables[mathrNames[4]].stateValues.value).eqls([ - "tuple", - 3, - 23, - -11, - ]); - expect(stateVariables[mathrNames[5]].stateValues.value).eqls([ - "tuple", - 3, - 3, - 3, - ]); - }); - }); - }); - - it("triple combination map", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let replacements = stateVariables["/_map1"].replacements; - let mathrNames = replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements.map( - (x) => x.componentName, - ), - ], - [], - ); - let mathrAnchors = mathrNames.map((x) => cesc2("#" + x)); - - cy.log("Test values displayed in browser"); - cy.get(`${mathrAnchors[0]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,21,−5)"); - }); - cy.get(`${mathrAnchors[1]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1,1)"); - }); - cy.get(`${mathrAnchors[2]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,21,−8)"); - }); - cy.get(`${mathrAnchors[3]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1,2)"); - }); - cy.get(`${mathrAnchors[4]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,23,−5)"); - }); - cy.get(`${mathrAnchors[5]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,2,1)"); - }); - cy.get(`${mathrAnchors[6]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,23,−8)"); - }); - cy.get(`${mathrAnchors[7]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,2,2)"); - }); - cy.get(`${mathrAnchors[8]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,21,−5)"); - }); - cy.get(`${mathrAnchors[9]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,1,1)"); - }); - cy.get(`${mathrAnchors[10]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,21,−8)"); - }); - cy.get(`${mathrAnchors[11]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,1,2)"); - }); - cy.get(`${mathrAnchors[12]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,23,−5)"); - }); - cy.get(`${mathrAnchors[13]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,2,1)"); - }); - cy.get(`${mathrAnchors[14]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,23,−8)"); - }); - cy.get(`${mathrAnchors[15]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,2,2)"); - }); - cy.get(`${mathrAnchors[16]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,21,−5)"); - }); - cy.get(`${mathrAnchors[17]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,1,1)"); - }); - cy.get(`${mathrAnchors[18]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,21,−8)"); - }); - cy.get(`${mathrAnchors[19]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,1,2)"); - }); - cy.get(`${mathrAnchors[20]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,23,−5)"); - }); - cy.get(`${mathrAnchors[21]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2,1)"); - }); - cy.get(`${mathrAnchors[22]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,23,−8)"); - }); - cy.get(`${mathrAnchors[23]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2,2)"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(() => { - expect(stateVariables[mathrNames[0]].stateValues.value).eqls([ - "tuple", - 1, - 21, - -5, - ]); - expect(stateVariables[mathrNames[1]].stateValues.value).eqls([ - "tuple", - 1, - 1, - 1, - ]); - expect(stateVariables[mathrNames[2]].stateValues.value).eqls([ - "tuple", - 1, - 21, - -8, - ]); - expect(stateVariables[mathrNames[3]].stateValues.value).eqls([ - "tuple", - 1, - 1, - 2, - ]); - expect(stateVariables[mathrNames[4]].stateValues.value).eqls([ - "tuple", - 1, - 23, - -5, - ]); - expect(stateVariables[mathrNames[5]].stateValues.value).eqls([ - "tuple", - 1, - 2, - 1, - ]); - expect(stateVariables[mathrNames[6]].stateValues.value).eqls([ - "tuple", - 1, - 23, - -8, - ]); - expect(stateVariables[mathrNames[7]].stateValues.value).eqls([ - "tuple", - 1, - 2, - 2, - ]); - expect(stateVariables[mathrNames[8]].stateValues.value).eqls([ - "tuple", - 2, - 21, - -5, - ]); - expect(stateVariables[mathrNames[9]].stateValues.value).eqls([ - "tuple", - 2, - 1, - 1, - ]); - expect(stateVariables[mathrNames[10]].stateValues.value).eqls([ - "tuple", - 2, - 21, - -8, - ]); - expect(stateVariables[mathrNames[11]].stateValues.value).eqls([ - "tuple", - 2, - 1, - 2, - ]); - expect(stateVariables[mathrNames[12]].stateValues.value).eqls([ - "tuple", - 2, - 23, - -5, - ]); - expect(stateVariables[mathrNames[13]].stateValues.value).eqls([ - "tuple", - 2, - 2, - 1, - ]); - expect(stateVariables[mathrNames[14]].stateValues.value).eqls([ - "tuple", - 2, - 23, - -8, - ]); - expect(stateVariables[mathrNames[15]].stateValues.value).eqls([ - "tuple", - 2, - 2, - 2, - ]); - expect(stateVariables[mathrNames[16]].stateValues.value).eqls([ - "tuple", - 3, - 21, - -5, - ]); - expect(stateVariables[mathrNames[17]].stateValues.value).eqls([ - "tuple", - 3, - 1, - 1, - ]); - expect(stateVariables[mathrNames[18]].stateValues.value).eqls([ - "tuple", - 3, - 21, - -8, - ]); - expect(stateVariables[mathrNames[19]].stateValues.value).eqls([ - "tuple", - 3, - 1, - 2, - ]); - expect(stateVariables[mathrNames[20]].stateValues.value).eqls([ - "tuple", - 3, - 23, - -5, - ]); - expect(stateVariables[mathrNames[21]].stateValues.value).eqls([ - "tuple", - 3, - 2, - 1, - ]); - expect(stateVariables[mathrNames[22]].stateValues.value).eqls([ - "tuple", - 3, - 23, - -8, - ]); - expect(stateVariables[mathrNames[23]].stateValues.value).eqls([ - "tuple", - 3, - 2, - 2, - ]); - }); - }); - }); - - it("parallel map with unequal numbers of iterates", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

- - 1 - 12 -

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_p1")).should("have.text", "hi"); - - cy.window().then(async (win) => { - let errorWarnings = await win.returnErrorWarnings1(); - - expect(errorWarnings.errors.length).eq(0); - expect(errorWarnings.warnings.length).eq(1); - - expect(errorWarnings.warnings[0].message).contain( - " has parallel behavior but different numbers of iterates in sources. Extra iterates will be ignored", - ); - expect(errorWarnings.warnings[0].level).eq(1); - expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(2); - expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(8); - expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(6); - expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(10); - }); - }); - - it("map with invalid behavior", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

- - 1 -

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_p1")).should("have.text", ""); - - cy.window().then(async (win) => { - let errorWarnings = await win.returnErrorWarnings1(); - - expect(errorWarnings.errors.length).eq(0); - expect(errorWarnings.warnings.length).eq(1); - - expect(errorWarnings.warnings[0].message).contain( - `Invalid map behavior: "bad"`, - ); - expect(errorWarnings.warnings[0].level).eq(1); - expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(2); - expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(8); - expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(5); - expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(10); - }); - }); - - it("two nested maps", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - -105 - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait for page to load - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let replacements = stateVariables["/_map1"].replacements; - let mathrNames = replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.reduce( - (a1, c1) => [ - ...a1, - ...stateVariables[ - c1.componentName - ].replacements.map((x) => x.componentName), - ], - [], - ), - ], - [], - ); - let mathrAnchors = mathrNames.map((x) => cesc2("#" + x)); - - cy.log("Test values displayed in browser"); - cy.get(`${mathrAnchors[0]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−9"); - }); - cy.get(`${mathrAnchors[1]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - cy.get(`${mathrAnchors[2]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−8"); - }); - cy.get(`${mathrAnchors[3]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(`${mathrAnchors[4]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6"); - }); - cy.get(`${mathrAnchors[5]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("5"); - }); - cy.get(`${mathrAnchors[6]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("7"); - }); - cy.get(`${mathrAnchors[7]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("6"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(() => { - expect(stateVariables[mathrNames[0]].stateValues.value).eq(-9); - expect(stateVariables[mathrNames[1]].stateValues.value).eq(3); - expect(stateVariables[mathrNames[2]].stateValues.value).eq(-8); - expect(stateVariables[mathrNames[3]].stateValues.value).eq(4); - expect(stateVariables[mathrNames[4]].stateValues.value).eq(6); - expect(stateVariables[mathrNames[5]].stateValues.value).eq(5); - expect(stateVariables[mathrNames[6]].stateValues.value).eq(7); - expect(stateVariables[mathrNames[7]].stateValues.value).eq(6); - }); - }); - }); - - it("three nested maps with graphs and copied", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - $_map1{name="mapcopy"} - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait for page to load - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let graphNames = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[x.componentName].replacements[0] - .componentName, - ); - let graphChildNames = graphNames.map((x) => - stateVariables[x].activeChildren.map((x) => x.componentName), - ); - let graphNames2 = stateVariables["/mapcopy"].replacements.map( - (x) => - stateVariables[x.componentName].replacements[0] - .componentName, - ); - let graph2ChildNames = graphNames2.map((x) => - stateVariables[x].activeChildren.map((x) => x.componentName), - ); - - expect( - stateVariables[graphNames[0]].stateValues.graphicalDescendants - .length, - ).eq(8); - expect( - stateVariables[graphNames[1]].stateValues.graphicalDescendants - .length, - ).eq(8); - expect( - stateVariables[graphNames2[0]].stateValues.graphicalDescendants - .length, - ).eq(8); - expect( - stateVariables[graphNames2[1]].stateValues.graphicalDescendants - .length, - ).eq(8); - - expect(stateVariables[graphChildNames[0][0]].stateValues.xs[0]).eq( - -9, - ); - expect(stateVariables[graphChildNames[0][0]].stateValues.xs[1]).eq( - -5, - ); - expect(stateVariables[graphChildNames[0][1]].stateValues.xs[0]).eq( - 3, - ); - expect(stateVariables[graphChildNames[0][1]].stateValues.xs[1]).eq( - 1, - ); - expect(stateVariables[graphChildNames[0][2]].stateValues.xs[0]).eq( - -8, - ); - expect(stateVariables[graphChildNames[0][2]].stateValues.xs[1]).eq( - -5, - ); - expect(stateVariables[graphChildNames[0][3]].stateValues.xs[0]).eq( - 4, - ); - expect(stateVariables[graphChildNames[0][3]].stateValues.xs[1]).eq( - 1, - ); - expect(stateVariables[graphChildNames[0][4]].stateValues.xs[0]).eq( - -9, - ); - expect(stateVariables[graphChildNames[0][4]].stateValues.xs[1]).eq( - 5, - ); - expect(stateVariables[graphChildNames[0][5]].stateValues.xs[0]).eq( - 3, - ); - expect(stateVariables[graphChildNames[0][5]].stateValues.xs[1]).eq( - 2, - ); - expect(stateVariables[graphChildNames[0][6]].stateValues.xs[0]).eq( - -8, - ); - expect(stateVariables[graphChildNames[0][6]].stateValues.xs[1]).eq( - 5, - ); - expect(stateVariables[graphChildNames[0][7]].stateValues.xs[0]).eq( - 4, - ); - expect(stateVariables[graphChildNames[0][7]].stateValues.xs[1]).eq( - 2, - ); - - expect(stateVariables[graphChildNames[1][0]].stateValues.xs[0]).eq( - 6, - ); - expect(stateVariables[graphChildNames[1][0]].stateValues.xs[1]).eq( - -5, - ); - expect(stateVariables[graphChildNames[1][1]].stateValues.xs[0]).eq( - 5, - ); - expect(stateVariables[graphChildNames[1][1]].stateValues.xs[1]).eq( - 1, - ); - expect(stateVariables[graphChildNames[1][2]].stateValues.xs[0]).eq( - 7, - ); - expect(stateVariables[graphChildNames[1][2]].stateValues.xs[1]).eq( - -5, - ); - expect(stateVariables[graphChildNames[1][3]].stateValues.xs[0]).eq( - 6, - ); - expect(stateVariables[graphChildNames[1][3]].stateValues.xs[1]).eq( - 1, - ); - expect(stateVariables[graphChildNames[1][4]].stateValues.xs[0]).eq( - 6, - ); - expect(stateVariables[graphChildNames[1][4]].stateValues.xs[1]).eq( - 5, - ); - expect(stateVariables[graphChildNames[1][5]].stateValues.xs[0]).eq( - 5, - ); - expect(stateVariables[graphChildNames[1][5]].stateValues.xs[1]).eq( - 2, - ); - expect(stateVariables[graphChildNames[1][6]].stateValues.xs[0]).eq( - 7, - ); - expect(stateVariables[graphChildNames[1][6]].stateValues.xs[1]).eq( - 5, - ); - expect(stateVariables[graphChildNames[1][7]].stateValues.xs[0]).eq( - 6, - ); - expect(stateVariables[graphChildNames[1][7]].stateValues.xs[1]).eq( - 2, - ); - - expect(stateVariables[graph2ChildNames[0][0]].stateValues.xs[0]).eq( - -9, - ); - expect(stateVariables[graph2ChildNames[0][0]].stateValues.xs[1]).eq( - -5, - ); - expect(stateVariables[graph2ChildNames[0][1]].stateValues.xs[0]).eq( - 3, - ); - expect(stateVariables[graph2ChildNames[0][1]].stateValues.xs[1]).eq( - 1, - ); - expect(stateVariables[graph2ChildNames[0][2]].stateValues.xs[0]).eq( - -8, - ); - expect(stateVariables[graph2ChildNames[0][2]].stateValues.xs[1]).eq( - -5, - ); - expect(stateVariables[graph2ChildNames[0][3]].stateValues.xs[0]).eq( - 4, - ); - expect(stateVariables[graph2ChildNames[0][3]].stateValues.xs[1]).eq( - 1, - ); - expect(stateVariables[graph2ChildNames[0][4]].stateValues.xs[0]).eq( - -9, - ); - expect(stateVariables[graph2ChildNames[0][4]].stateValues.xs[1]).eq( - 5, - ); - expect(stateVariables[graph2ChildNames[0][5]].stateValues.xs[0]).eq( - 3, - ); - expect(stateVariables[graph2ChildNames[0][5]].stateValues.xs[1]).eq( - 2, - ); - expect(stateVariables[graph2ChildNames[0][6]].stateValues.xs[0]).eq( - -8, - ); - expect(stateVariables[graph2ChildNames[0][6]].stateValues.xs[1]).eq( - 5, - ); - expect(stateVariables[graph2ChildNames[0][7]].stateValues.xs[0]).eq( - 4, - ); - expect(stateVariables[graph2ChildNames[0][7]].stateValues.xs[1]).eq( - 2, - ); - - expect(stateVariables[graph2ChildNames[1][0]].stateValues.xs[0]).eq( - 6, - ); - expect(stateVariables[graph2ChildNames[1][0]].stateValues.xs[1]).eq( - -5, - ); - expect(stateVariables[graph2ChildNames[1][1]].stateValues.xs[0]).eq( - 5, - ); - expect(stateVariables[graph2ChildNames[1][1]].stateValues.xs[1]).eq( - 1, - ); - expect(stateVariables[graph2ChildNames[1][2]].stateValues.xs[0]).eq( - 7, - ); - expect(stateVariables[graph2ChildNames[1][2]].stateValues.xs[1]).eq( - -5, - ); - expect(stateVariables[graph2ChildNames[1][3]].stateValues.xs[0]).eq( - 6, - ); - expect(stateVariables[graph2ChildNames[1][3]].stateValues.xs[1]).eq( - 1, - ); - expect(stateVariables[graph2ChildNames[1][4]].stateValues.xs[0]).eq( - 6, - ); - expect(stateVariables[graph2ChildNames[1][4]].stateValues.xs[1]).eq( - 5, - ); - expect(stateVariables[graph2ChildNames[1][5]].stateValues.xs[0]).eq( - 5, - ); - expect(stateVariables[graph2ChildNames[1][5]].stateValues.xs[1]).eq( - 2, - ); - expect(stateVariables[graph2ChildNames[1][6]].stateValues.xs[0]).eq( - 7, - ); - expect(stateVariables[graph2ChildNames[1][6]].stateValues.xs[1]).eq( - 5, - ); - expect(stateVariables[graph2ChildNames[1][7]].stateValues.xs[0]).eq( - 6, - ); - expect(stateVariables[graph2ChildNames[1][7]].stateValues.xs[1]).eq( - 2, - ); - }); - }); - - it("three nested maps with graphs and assignnames", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait for page to load - - cy.log("Test values displayed in browser"); - cy.get(cesc(`#\\/c1`) + ` .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−9,−5)"); - }); - cy.get(cesc(`#\\/c2`) + ` .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−8,−5)"); - }); - cy.get(cesc(`#\\/c3`) + ` .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−9,5)"); - }); - cy.get(cesc(`#\\/c4`) + ` .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−8,5)"); - }); - cy.get(cesc(`#\\/c5`) + ` .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(6,−5)"); - }); - cy.get(cesc(`#\\/c6`) + ` .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(7,−5)"); - }); - cy.get(cesc(`#\\/c7`) + ` .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(6,5)"); - }); - cy.get(cesc(`#\\/c8`) + ` .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(7,5)"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect( - stateVariables["/u/_graph1"].stateValues.graphicalDescendants - .length, - ).eq(4); - expect( - stateVariables["/v/_graph1"].stateValues.graphicalDescendants - .length, - ).eq(4); - expect(stateVariables["/u/u/u/A"].stateValues.xs[0]).eq(-9); - expect(stateVariables["/u/u/u/A"].stateValues.xs[1]).eq(-5); - expect(stateVariables["/u/u/v/A"].stateValues.xs[0]).eq(-8); - expect(stateVariables["/u/u/v/A"].stateValues.xs[1]).eq(-5); - expect(stateVariables["/u/v/u/A"].stateValues.xs[0]).eq(-9); - expect(stateVariables["/u/v/u/A"].stateValues.xs[1]).eq(5); - expect(stateVariables["/u/v/v/A"].stateValues.xs[0]).eq(-8); - expect(stateVariables["/u/v/v/A"].stateValues.xs[1]).eq(5); - expect(stateVariables["/v/u/u/A"].stateValues.xs[0]).eq(6); - expect(stateVariables["/v/u/u/A"].stateValues.xs[1]).eq(-5); - expect(stateVariables["/v/u/v/A"].stateValues.xs[0]).eq(7); - expect(stateVariables["/v/u/v/A"].stateValues.xs[1]).eq(-5); - expect(stateVariables["/v/v/u/A"].stateValues.xs[0]).eq(6); - expect(stateVariables["/v/v/u/A"].stateValues.xs[1]).eq(5); - expect(stateVariables["/v/v/v/A"].stateValues.xs[0]).eq(7); - expect(stateVariables["/v/v/v/A"].stateValues.xs[1]).eq(5); - }); - }); - - it("combination map nested inside map with graphs", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); //wait for window to load - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let graphNames = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[x.componentName].replacements[0] - .componentName, - ); - let graphChildNames = graphNames.map((x) => - stateVariables[x].activeChildren.map((x) => x.componentName), - ); - - expect( - stateVariables[graphNames[0]].stateValues.graphicalDescendants - .length, - ).eq(4); - expect( - stateVariables[graphNames[1]].stateValues.graphicalDescendants - .length, - ).eq(4); - expect(stateVariables[graphChildNames[0][0]].stateValues.xs[0]).eq( - -9, - ); - expect(stateVariables[graphChildNames[0][0]].stateValues.xs[1]).eq( - -5, - ); - expect(stateVariables[graphChildNames[0][1]].stateValues.xs[0]).eq( - -9, - ); - expect(stateVariables[graphChildNames[0][1]].stateValues.xs[1]).eq( - 5, - ); - expect(stateVariables[graphChildNames[0][2]].stateValues.xs[0]).eq( - -8, - ); - expect(stateVariables[graphChildNames[0][2]].stateValues.xs[1]).eq( - -5, - ); - expect(stateVariables[graphChildNames[0][3]].stateValues.xs[0]).eq( - -8, - ); - expect(stateVariables[graphChildNames[0][3]].stateValues.xs[1]).eq( - 5, - ); - - expect(stateVariables[graphChildNames[1][0]].stateValues.xs[0]).eq( - 6, - ); - expect(stateVariables[graphChildNames[1][0]].stateValues.xs[1]).eq( - -5, - ); - expect(stateVariables[graphChildNames[1][1]].stateValues.xs[0]).eq( - 6, - ); - expect(stateVariables[graphChildNames[1][1]].stateValues.xs[1]).eq( - 5, - ); - expect(stateVariables[graphChildNames[1][2]].stateValues.xs[0]).eq( - 7, - ); - expect(stateVariables[graphChildNames[1][2]].stateValues.xs[1]).eq( - -5, - ); - expect(stateVariables[graphChildNames[1][3]].stateValues.xs[0]).eq( - 7, - ); - expect(stateVariables[graphChildNames[1][3]].stateValues.xs[1]).eq( - 5, - ); - }); - }); - - it("map with copies", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - x - $_map1{name="mapcopy"} - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); //wait for window to load - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let replacementNames = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements.map( - (x) => x.componentName, - ), - ], - [], - ); - let replacementAnchors = replacementNames.map((x) => - cesc2("#" + x), - ); - let replacementNames2 = stateVariables[ - "/mapcopy" - ].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements.map( - (x) => x.componentName, - ), - ], - [], - ); - let replacementAnchors2 = replacementNames2.map((x) => - cesc2("#" + x), - ); - - cy.log("Test values displayed in browser"); - cy.get(`${replacementAnchors[0]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+2z+4"); - }); - cy.get(`${replacementAnchors[1]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(`${replacementAnchors[2]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+2z+8"); - }); - cy.get(`${replacementAnchors[3]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - - cy.get(`${cesc2("#/a")} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - - cy.get(`${replacementAnchors2[0]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+2z+4"); - }); - cy.get(`${replacementAnchors2[1]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(`${replacementAnchors2[2]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+2z+8"); - }); - cy.get(`${replacementAnchors2[3]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - }); - }); - - it("map with copies, extended dynamically", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 1 - - - - - x - $_map1{name="mapcopy"} - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); //wait for window to load - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let replacementNames = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements.map( - (x) => x.componentName, - ), - ], - [], - ); - let replacementAnchors = replacementNames.map((x) => - cesc2("#" + x), - ); - let replacementNames2 = stateVariables[ - "/mapcopy" - ].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements.map( - (x) => x.componentName, - ), - ], - [], - ); - let replacementAnchors2 = replacementNames2.map((x) => - cesc2("#" + x), - ); - - cy.log("Test values displayed in browser"); - cy.get(`${replacementAnchors[0]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+2z+4"); - }); - cy.get(`${replacementAnchors[1]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(`${cesc2("#/a")} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(`${replacementAnchors2[0]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+2z+4"); - }); - cy.get(`${replacementAnchors2[1]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - }); - - cy.log("Double the length then test again"); - cy.get(cesc2("#/_updatevalue1_button")).click(); //Update Button - cy.get(cesc2("#/length")).should("contain.text", "2"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let replacementNames = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements.map( - (x) => x.componentName, - ), - ], - [], - ); - let replacementAnchors = replacementNames.map((x) => - cesc2("#" + x), - ); - let replacementNames2 = stateVariables[ - "/mapcopy" - ].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements.map( - (x) => x.componentName, - ), - ], - [], - ); - let replacementAnchors2 = replacementNames2.map((x) => - cesc2("#" + x), - ); - - cy.get(`${replacementAnchors[0]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+2z+4"); - }); - cy.get(`${replacementAnchors[1]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(`${replacementAnchors[2]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+2z+8"); - }); - cy.get(`${replacementAnchors[3]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(`${cesc2("#/a")} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(`${replacementAnchors2[0]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+2z+4"); - }); - cy.get(`${replacementAnchors2[1]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(`${replacementAnchors2[2]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+2z+8"); - }); - cy.get(`${replacementAnchors2[3]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - }); - - cy.log("Double the length again then test one more time"); - cy.get(cesc2("#/_updatevalue1_button")).click(); //Update Button - cy.get(cesc2("#/length")).should("contain.text", "4"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let replacementNames = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements.map( - (x) => x.componentName, - ), - ], - [], - ); - let replacementAnchors = replacementNames.map((x) => - cesc2("#" + x), - ); - let replacementNames2 = stateVariables[ - "/mapcopy" - ].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[c.componentName].replacements.map( - (x) => x.componentName, - ), - ], - [], - ); - let replacementAnchors2 = replacementNames2.map((x) => - cesc2("#" + x), - ); - - cy.get(`${replacementAnchors[0]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+2z+4"); - }); - cy.get(`${replacementAnchors[1]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(`${replacementAnchors[2]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+2z+8"); - }); - cy.get(`${replacementAnchors[3]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(`${replacementAnchors[4]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+2z+12"); - }); - cy.get(`${replacementAnchors[5]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(`${replacementAnchors[6]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+2z+16"); - }); - cy.get(`${replacementAnchors[7]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(`${cesc2("#/a")} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(`${replacementAnchors2[0]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+2z+4"); - }); - cy.get(`${replacementAnchors2[1]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(`${replacementAnchors2[2]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+2z+8"); - }); - cy.get(`${replacementAnchors2[3]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(`${replacementAnchors2[4]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+2z+12"); - }); - cy.get(`${replacementAnchors2[5]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(`${replacementAnchors2[6]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x+2z+16"); - }); - cy.get(`${replacementAnchors2[7]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - }); - }); - - it("map with copied template", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - xy - - - - $_template1 - qp - - - $_map2{name="mapcopy"} - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); //wait for window to load - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let replacementNames = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[x.componentName].replacements[0] - .componentName, - ); - let replacementAnchors = replacementNames.map((x) => - cesc2("#" + x), - ); - let replacementNames2 = stateVariables["/_map2"].replacements.map( - (x) => - stateVariables[x.componentName].replacements[0] - .componentName, - ); - let replacementAnchors2 = replacementNames2.map((x) => - cesc2("#" + x), - ); - let replacementNames3 = stateVariables["/mapcopy"].replacements.map( - (x) => - stateVariables[x.componentName].replacements[0] - .componentName, - ); - let replacementAnchors3 = replacementNames3.map((x) => - cesc2("#" + x), - ); - - cy.log("Test values displayed in browser"); - cy.get(`${replacementAnchors[0]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(x)"); - }); - cy.get(`${replacementAnchors[1]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(2y)"); - }); - cy.get(`${replacementAnchors2[0]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(q)"); - }); - cy.get(`${replacementAnchors2[1]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(2p)"); - }); - cy.get(`${replacementAnchors3[0]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(q)"); - }); - cy.get(`${replacementAnchors3[1]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(2p)"); - }); - }); - }); - - it("map with new namespace but no new namespace on template", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - xy - - - $_map1{name="mapcopy"} - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); //wait for window to load - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let replacementNames = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[x.componentName].replacements[0] - .componentName, - ); - let replacementAnchors = replacementNames.map((x) => - cesc2("#" + x), - ); - let replacementNames2 = stateVariables["/mapcopy"].replacements.map( - (x) => - stateVariables[x.componentName].replacements[0] - .componentName, - ); - let replacementAnchors2 = replacementNames2.map((x) => - cesc2("#" + x), - ); - - cy.log("Test values displayed in browser"); - cy.get(`${replacementAnchors[0]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(x)"); - }); - cy.get(`${replacementAnchors[1]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(2y)"); - }); - cy.get(`${replacementAnchors2[0]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(x)"); - }); - cy.get(`${replacementAnchors2[1]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(2y)"); - }); - }); - }); - - it("graph with new namespace and assignnames", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - $(/hi/c/_point1.coords{assignNames="c1"}) - $(/hi/s/_point1.coords{assignNames="c2"}) - $(/hi/q/_point1.coords{assignNames="c3"}) - - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); //wait for window to load - - cy.log("Test values displayed in browser"); - - cy.get(cesc(`#\\/c1`) + ` .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,−2)"); - }); - cy.get(cesc(`#\\/c2`) + ` .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,−3)"); - }); - cy.get(cesc(`#\\/c3`) + ` .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,−3)"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let replacementNames = stateVariables["/hi/_map1"].replacements.map( - (x) => - stateVariables[x.componentName].replacements[0] - .componentName, - ); - - expect( - stateVariables["/hi"].stateValues.graphicalDescendants.length, - ).eq(4); - expect(stateVariables["/hi/q/_point1"].stateValues.xs[0]).eq(1); - expect(stateVariables["/hi/q/_point1"].stateValues.xs[1]).eq(-3); - expect(stateVariables["/hi/c/_point1"].stateValues.xs[0]).eq(1); - expect(stateVariables["/hi/c/_point1"].stateValues.xs[1]).eq(-2); - expect(stateVariables["/hi/s/_point1"].stateValues.xs[0]).eq(2); - expect(stateVariables["/hi/s/_point1"].stateValues.xs[1]).eq(-3); - expect(stateVariables[replacementNames[3]].stateValues.xs[0]).eq(2); - expect(stateVariables[replacementNames[3]].stateValues.xs[1]).eq( - -2, - ); - }); - }); - - it("map copying source of other map", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); //wait for window to load - - cy.log("Test values displayed in browser"); - cy.get(`${cesc2("#/u/_math1")} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,6)"); - }); - cy.get(`${cesc2("#/v/_math1")} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,6)"); - }); - cy.get(`${cesc2("#/w/_math1")} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,6)"); - }); - cy.get(`${cesc2("#/c/_math1")} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(4)"); - }); - cy.get(`${cesc2("#/d/_math1")} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(5)"); - }); - cy.get(`${cesc2("#/e/_math1")} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(6)"); - }); - }); - - it("map length depending on other map", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); //wait for window to load - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let replacementNames = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[x.componentName].replacements[0] - .componentName, - ); - let replacementAnchors = replacementNames.map((x) => - stateVariables[x].replacements.map((y) => - cesc2( - "#" + - stateVariables[y.componentName].replacements[0] - .componentName, - ), - ), - ); - - cy.log("Test values displayed in browser"); - cy.get(`${replacementAnchors[0][0]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,1)"); - }); - cy.get(`${replacementAnchors[1][0]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,2)"); - }); - cy.get(`${replacementAnchors[1][1]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,2)"); - }); - cy.get(`${replacementAnchors[2][0]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,3)"); - }); - cy.get(`${replacementAnchors[2][1]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,3)"); - }); - cy.get(`${replacementAnchors[2][2]} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,3)"); - }); - }); - }); - - it("map begins zero length, copied multiple times", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

- - - - - - -

- - - - - -

$_map1{name="copymap2"}

-

$copymap2{name="copymap3"}

- - $_p1{name="p4"} - $p4{name="p5"} - $p5{name="p6"} - - $sequenceCount.value{assignNames="sequenceCount2"} - $sequenceTo.value{assignNames="sequenceTo2"} - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); //wait for window to load - cy.log("At beginning, nothing shown"); - cy.get(cesc2("#/_p1")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - cy.get(cesc2("#/_p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - cy.get(cesc2("#/_p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - cy.get(cesc2("#/p4")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - cy.get(cesc2("#/p5")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - cy.get(cesc2("#/p6")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - - cy.log("make sequence length 1"); - cy.get(cesc2("#/sequenceCount") + " textarea").type( - "{end}{backspace}1{enter}", - { force: true }, - ); - cy.get(cesc2("#/sequenceCount2")).should("contain.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let map1mathNames = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[x.componentName].replacements[0] - .componentName, - ); - let map1mathAnchors = map1mathNames.map((x) => cesc2("#" + x)); - let map2mathNames = stateVariables["/copymap2"].replacements.map( - (x) => - stateVariables[x.componentName].replacements[0] - .componentName, - ); - let map2mathAnchors = map2mathNames.map((x) => cesc2("#" + x)); - let map3mathNames = stateVariables["/copymap3"].replacements.map( - (x) => - stateVariables[x.componentName].replacements[0] - .componentName, - ); - let map3mathAnchors = map3mathNames.map((x) => cesc2("#" + x)); - let map4mathNames = stateVariables["/p4"].activeChildren - .filter((x) => x.componentType === "math") - .map((x) => x.componentName); - let map4mathAnchors = map4mathNames.map((x) => cesc2("#" + x)); - let map5mathNames = stateVariables["/p5"].activeChildren - .filter((x) => x.componentType === "math") - .map((x) => x.componentName); - let map5mathAnchors = map5mathNames.map((x) => cesc2("#" + x)); - let map6mathNames = stateVariables["/p6"].activeChildren - .filter((x) => x.componentType === "math") - .map((x) => x.componentName); - let map6mathAnchors = map6mathNames.map((x) => cesc2("#" + x)); - - cy.get(cesc2("#/_p1")) - .find(map1mathAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc2("#/_p2")) - .find(map2mathAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc2("#/_p3")) - .find(map3mathAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc2("#/p4")) - .find(map4mathAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc2("#/p5")) - .find(map5mathAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc2("#/p6")) - .find(map6mathAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - }); - - cy.log("make sequence length 0 again"); - cy.get(cesc2("#/sequenceCount") + " textarea").type( - "{end}{backspace}0{enter}", - { force: true }, - ); - cy.get(cesc2("#/sequenceCount2")).should("contain.text", "0"); - - cy.get(cesc2("#/_p1")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - cy.get(cesc2("#/_p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - cy.get(cesc2("#/_p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - cy.get(cesc2("#/p4")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - cy.get(cesc2("#/p5")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - cy.get(cesc2("#/p6")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - - cy.log("make sequence length 2"); - cy.get(cesc2("#/sequenceCount") + " textarea").type( - "{end}{backspace}2{enter}", - { force: true }, - ); - cy.get(cesc2("#/sequenceCount2")).should("contain.text", "2"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let map1mathNames = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[x.componentName].replacements[0] - .componentName, - ); - let map1mathAnchors = map1mathNames.map((x) => cesc2("#" + x)); - let map2mathNames = stateVariables["/copymap2"].replacements.map( - (x) => - stateVariables[x.componentName].replacements[0] - .componentName, - ); - let map2mathAnchors = map2mathNames.map((x) => cesc2("#" + x)); - let map3mathNames = stateVariables["/copymap3"].replacements.map( - (x) => - stateVariables[x.componentName].replacements[0] - .componentName, - ); - let map3mathAnchors = map3mathNames.map((x) => cesc2("#" + x)); - let map4mathNames = stateVariables["/p4"].activeChildren - .filter((x) => x.componentType === "math") - .map((x) => x.componentName); - let map4mathAnchors = map4mathNames.map((x) => cesc2("#" + x)); - let map5mathNames = stateVariables["/p5"].activeChildren - .filter((x) => x.componentType === "math") - .map((x) => x.componentName); - let map5mathAnchors = map5mathNames.map((x) => cesc2("#" + x)); - let map6mathNames = stateVariables["/p6"].activeChildren - .filter((x) => x.componentType === "math") - .map((x) => x.componentName); - let map6mathAnchors = map6mathNames.map((x) => cesc2("#" + x)); - - cy.get(cesc2("#/_p1")) - .find(map1mathAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc2("#/_p1")) - .find(map1mathAnchors[1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc2("#/_p2")) - .find(map2mathAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc2("#/_p2")) - .find(map2mathAnchors[1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc2("#/_p3")) - .find(map3mathAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc2("#/_p3")) - .find(map3mathAnchors[1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc2("#/p4")) - .find(map4mathAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc2("#/p4")) - .find(map4mathAnchors[1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc2("#/p5")) - .find(map5mathAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc2("#/p5")) - .find(map5mathAnchors[1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - cy.get(cesc2("#/p6")) - .find(map6mathAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc2("#/p6")) - .find(map6mathAnchors[1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4"); - }); - }); - - cy.log("change limits"); - cy.get(cesc2("#/sequenceFrom") + " textarea").type( - "{end}{backspace}3{enter}", - { force: true }, - ); - cy.get(cesc2("#/sequenceTo") + " textarea").type( - "{end}{backspace}5{enter}", - { force: true }, - ); - cy.get(cesc2("#/sequenceTo2")).should("contain.text", "5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let map1mathNames = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[x.componentName].replacements[0] - .componentName, - ); - let map1mathAnchors = map1mathNames.map((x) => cesc2("#" + x)); - let map2mathNames = stateVariables["/copymap2"].replacements.map( - (x) => - stateVariables[x.componentName].replacements[0] - .componentName, - ); - let map2mathAnchors = map2mathNames.map((x) => cesc2("#" + x)); - let map3mathNames = stateVariables["/copymap3"].replacements.map( - (x) => - stateVariables[x.componentName].replacements[0] - .componentName, - ); - let map3mathAnchors = map3mathNames.map((x) => cesc2("#" + x)); - let map4mathNames = stateVariables["/p4"].activeChildren - .filter((x) => x.componentType === "math") - .map((x) => x.componentName); - let map4mathAnchors = map4mathNames.map((x) => cesc2("#" + x)); - let map5mathNames = stateVariables["/p5"].activeChildren - .filter((x) => x.componentType === "math") - .map((x) => x.componentName); - let map5mathAnchors = map5mathNames.map((x) => cesc2("#" + x)); - let map6mathNames = stateVariables["/p6"].activeChildren - .filter((x) => x.componentType === "math") - .map((x) => x.componentName); - let map6mathAnchors = map6mathNames.map((x) => cesc2("#" + x)); - - cy.get(cesc2("#/_p1")) - .find(map1mathAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9"); - }); - cy.get(cesc2("#/_p1")) - .find(map1mathAnchors[1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("25"); - }); - cy.get(cesc2("#/_p2")) - .find(map2mathAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9"); - }); - cy.get(cesc2("#/_p2")) - .find(map2mathAnchors[1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("25"); - }); - cy.get(cesc2("#/_p3")) - .find(map3mathAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9"); - }); - cy.get(cesc2("#/_p3")) - .find(map3mathAnchors[1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("25"); - }); - cy.get(cesc2("#/p4")) - .find(map4mathAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9"); - }); - cy.get(cesc2("#/p4")) - .find(map4mathAnchors[1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("25"); - }); - cy.get(cesc2("#/p5")) - .find(map5mathAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9"); - }); - cy.get(cesc2("#/p5")) - .find(map5mathAnchors[1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("25"); - }); - cy.get(cesc2("#/p6")) - .find(map6mathAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9"); - }); - cy.get(cesc2("#/p6")) - .find(map6mathAnchors[1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("25"); - }); - }); - - cy.log("make sequence length 0 again"); - cy.get(cesc2("#/sequenceCount") + " textarea").type( - "{end}{backspace}0{enter}", - { force: true }, - ); - cy.get(cesc2("#/sequenceCount2")).should("contain.text", "0"); - - cy.get(cesc2("#/_p1")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - cy.get(cesc2("#/_p2")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - cy.get(cesc2("#/_p3")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - cy.get(cesc2("#/p4")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - cy.get(cesc2("#/p5")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - cy.get(cesc2("#/p6")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - - cy.log("make sequence length 3"); - cy.get(cesc2("#/sequenceCount") + " textarea").type( - "{end}{backspace}3{enter}", - { force: true }, - ); - cy.get(cesc2("#/sequenceCount2")).should("contain.text", "3"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let map1mathNames = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[x.componentName].replacements[0] - .componentName, - ); - let map1mathAnchors = map1mathNames.map((x) => cesc2("#" + x)); - let map2mathNames = stateVariables["/copymap2"].replacements.map( - (x) => - stateVariables[x.componentName].replacements[0] - .componentName, - ); - let map2mathAnchors = map2mathNames.map((x) => cesc2("#" + x)); - let map3mathNames = stateVariables["/copymap3"].replacements.map( - (x) => - stateVariables[x.componentName].replacements[0] - .componentName, - ); - let map3mathAnchors = map3mathNames.map((x) => cesc2("#" + x)); - let map4mathNames = stateVariables["/p4"].activeChildren - .filter((x) => x.componentType === "math") - .map((x) => x.componentName); - let map4mathAnchors = map4mathNames.map((x) => cesc2("#" + x)); - let map5mathNames = stateVariables["/p5"].activeChildren - .filter((x) => x.componentType === "math") - .map((x) => x.componentName); - let map5mathAnchors = map5mathNames.map((x) => cesc2("#" + x)); - let map6mathNames = stateVariables["/p6"].activeChildren - .filter((x) => x.componentType === "math") - .map((x) => x.componentName); - let map6mathAnchors = map6mathNames.map((x) => cesc2("#" + x)); - - cy.get(cesc2("#/_p1")) - .find(map1mathAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9"); - }); - cy.get(cesc2("#/_p1")) - .find(map1mathAnchors[1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("16"); - }); - cy.get(cesc2("#/_p1")) - .find(map1mathAnchors[2]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("25"); - }); - cy.get(cesc2("#/_p2")) - .find(map2mathAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9"); - }); - cy.get(cesc2("#/_p2")) - .find(map2mathAnchors[1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("16"); - }); - cy.get(cesc2("#/_p2")) - .find(map2mathAnchors[2]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("25"); - }); - cy.get(cesc2("#/_p3")) - .find(map3mathAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9"); - }); - cy.get(cesc2("#/_p3")) - .find(map3mathAnchors[1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("16"); - }); - cy.get(cesc2("#/_p3")) - .find(map3mathAnchors[2]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("25"); - }); - cy.get(cesc2("#/p4")) - .find(map4mathAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9"); - }); - cy.get(cesc2("#/p4")) - .find(map4mathAnchors[1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("16"); - }); - cy.get(cesc2("#/p4")) - .find(map4mathAnchors[2]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("25"); - }); - cy.get(cesc2("#/p5")) - .find(map5mathAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9"); - }); - cy.get(cesc2("#/p5")) - .find(map5mathAnchors[1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("16"); - }); - cy.get(cesc2("#/p5")) - .find(map5mathAnchors[2]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("25"); - }); - cy.get(cesc2("#/p6")) - .find(map6mathAnchors[0]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9"); - }); - cy.get(cesc2("#/p6")) - .find(map6mathAnchors[1]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("16"); - }); - cy.get(cesc2("#/p6")) - .find(map6mathAnchors[2]) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("25"); - }); - }); - }); - - it("map with circular dependence in template", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - 1 - 1 - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); //wait for window to load - - cy.log("Test values displayed in browser"); - - cy.get(cesc(`#\\/c1`) + ` .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(4,2)"); - }); - cy.get(cesc(`#\\/c2`) + ` .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,4)"); - }); - cy.get(cesc(`#\\/c3`) + ` .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(9,3)"); - }); - cy.get(cesc(`#\\/c4`) + ` .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,9)"); - }); - cy.get(cesc(`#\\/c5`) + ` .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(16,4)"); - }); - cy.get(cesc(`#\\/c6`) + ` .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(4,16)"); - }); - cy.get(`${cesc2("#/q")} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(`${cesc2("#/r")} .mjx-mrow`) - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - cy.window().then(async (win) => { - let r = 1; - let q = 1; - let s = [2, 3, 4]; - let xs1 = s.map((v) => v * v * q); - let xs2 = s.map((v) => v * r); - let ns = ["a", "b", "c"]; - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_graph1"].stateValues.graphicalDescendants - .length, - ).eq(6); - for (let ind = 0; ind < 3; ind++) { - let namespace = ns[ind]; - expect( - stateVariables[`/${namespace}/_point1`].stateValues.xs[0], - ).eq(xs1[ind]); - expect( - stateVariables[`/${namespace}/_point1`].stateValues.xs[1], - ).eq(xs2[ind]); - expect( - stateVariables[`/${namespace}/_point2`].stateValues.xs[0], - ).eq(xs2[ind]); - expect( - stateVariables[`/${namespace}/_point2`].stateValues.xs[1], - ).eq(xs1[ind]); - } - }); - - cy.log("move point a1"); - cy.window().then(async (win) => { - let r = 1.3; - let q = -2.1; - let s = [2, 3, 4]; - let xs1 = s.map((v) => v * v * q); - let xs2 = s.map((v) => v * r); - let ns = ["a", "b", "c"]; - - await win.callAction1({ - actionName: "movePoint", - componentName: "/a/_point1", - args: { x: xs1[0], y: xs2[0] }, - }); - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 0; ind < 3; ind++) { - let namespace = ns[ind]; - expect( - stateVariables[`/${namespace}/_point1`].stateValues.xs[0], - ).closeTo(xs1[ind], 1e-14); - expect( - stateVariables[`/${namespace}/_point1`].stateValues.xs[1], - ).closeTo(xs2[ind], 1e-14); - expect( - stateVariables[`/${namespace}/_point2`].stateValues.xs[0], - ).closeTo(xs2[ind], 1e-14); - expect( - stateVariables[`/${namespace}/_point2`].stateValues.xs[1], - ).closeTo(xs1[ind], 1e-14); - } - }); - - cy.log("move point a2"); - cy.window().then(async (win) => { - let r = 0.7; - let q = 1.8; - let s = [2, 3, 4]; - let xs1 = s.map((v) => v * v * q); - let xs2 = s.map((v) => v * r); - let ns = ["a", "b", "c"]; - - await win.callAction1({ - actionName: "movePoint", - componentName: "/a/_point2", - args: { x: xs2[0], y: xs1[0] }, - }); - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 0; ind < 3; ind++) { - let namespace = ns[ind]; - expect( - stateVariables[`/${namespace}/_point1`].stateValues.xs[0], - ).closeTo(xs1[ind], 1e-14); - expect( - stateVariables[`/${namespace}/_point1`].stateValues.xs[1], - ).closeTo(xs2[ind], 1e-14); - expect( - stateVariables[`/${namespace}/_point2`].stateValues.xs[0], - ).closeTo(xs2[ind], 1e-14); - expect( - stateVariables[`/${namespace}/_point2`].stateValues.xs[1], - ).closeTo(xs1[ind], 1e-14); - } - }); - - cy.log("move point b1"); - cy.window().then(async (win) => { - let r = -0.2; - let q = 0.3; - let s = [2, 3, 4]; - let xs1 = s.map((v) => v * v * q); - let xs2 = s.map((v) => v * r); - let ns = ["a", "b", "c"]; - - await win.callAction1({ - actionName: "movePoint", - componentName: "/b/_point1", - args: { x: xs1[1], y: xs2[1] }, - }); - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 0; ind < 3; ind++) { - let namespace = ns[ind]; - expect( - stateVariables[`/${namespace}/_point1`].stateValues.xs[0], - ).closeTo(xs1[ind], 1e-14); - expect( - stateVariables[`/${namespace}/_point1`].stateValues.xs[1], - ).closeTo(xs2[ind], 1e-14); - expect( - stateVariables[`/${namespace}/_point2`].stateValues.xs[0], - ).closeTo(xs2[ind], 1e-14); - expect( - stateVariables[`/${namespace}/_point2`].stateValues.xs[1], - ).closeTo(xs1[ind], 1e-14); - } - }); - - cy.log("move point b2"); - cy.window().then(async (win) => { - let r = 0.6; - let q = 0.35; - let s = [2, 3, 4]; - let xs1 = s.map((v) => v * v * q); - let xs2 = s.map((v) => v * r); - let ns = ["a", "b", "c"]; - - await win.callAction1({ - actionName: "movePoint", - componentName: "/b/_point2", - args: { x: xs2[1], y: xs1[1] }, - }); - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 0; ind < 3; ind++) { - let namespace = ns[ind]; - expect( - stateVariables[`/${namespace}/_point1`].stateValues.xs[0], - ).closeTo(xs1[ind], 1e-14); - expect( - stateVariables[`/${namespace}/_point1`].stateValues.xs[1], - ).closeTo(xs2[ind], 1e-14); - expect( - stateVariables[`/${namespace}/_point2`].stateValues.xs[0], - ).closeTo(xs2[ind], 1e-14); - expect( - stateVariables[`/${namespace}/_point2`].stateValues.xs[1], - ).closeTo(xs1[ind], 1e-14); - } - }); - - cy.log("move point c1"); - cy.window().then(async (win) => { - let r = -0.21; - let q = -0.46; - let s = [2, 3, 4]; - let xs1 = s.map((v) => v * v * q); - let xs2 = s.map((v) => v * r); - let ns = ["a", "b", "c"]; - - await win.callAction1({ - actionName: "movePoint", - componentName: "/c/_point1", - args: { x: xs1[2], y: xs2[2] }, - }); - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 0; ind < 3; ind++) { - let namespace = ns[ind]; - expect( - stateVariables[`/${namespace}/_point1`].stateValues.xs[0], - ).closeTo(xs1[ind], 1e-14); - expect( - stateVariables[`/${namespace}/_point1`].stateValues.xs[1], - ).closeTo(xs2[ind], 1e-14); - expect( - stateVariables[`/${namespace}/_point2`].stateValues.xs[0], - ).closeTo(xs2[ind], 1e-14); - expect( - stateVariables[`/${namespace}/_point2`].stateValues.xs[1], - ).closeTo(xs1[ind], 1e-14); - } - }); - - cy.log("move point c2"); - cy.window().then(async (win) => { - let r = 0.37; - let q = -0.73; - let s = [2, 3, 4]; - let xs1 = s.map((v) => v * v * q); - let xs2 = s.map((v) => v * r); - let ns = ["a", "b", "c"]; - - await win.callAction1({ - actionName: "movePoint", - componentName: "/c/_point2", - args: { x: xs2[2], y: xs1[2] }, - }); - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 0; ind < 3; ind++) { - let namespace = ns[ind]; - expect( - stateVariables[`/${namespace}/_point1`].stateValues.xs[0], - ).closeTo(xs1[ind], 1e-14); - expect( - stateVariables[`/${namespace}/_point1`].stateValues.xs[1], - ).closeTo(xs2[ind], 1e-14); - expect( - stateVariables[`/${namespace}/_point2`].stateValues.xs[0], - ).closeTo(xs2[ind], 1e-14); - expect( - stateVariables[`/${namespace}/_point2`].stateValues.xs[1], - ).closeTo(xs1[ind], 1e-14); - } - }); - }); - - it("two maps with mutual copies, begin zero length, copied multiple times", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- $sequenceCount.value{assignNames="sequenceCount2"} - $sequenceTo.value{assignNames="sequenceTo2"} - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); //wait for window to load - - cy.log("At beginning, nothing shown"); - cy.get(cesc2("#/_p1")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_graph1"].stateValues.graphicalDescendants - .length, - ).eq(0); - expect( - stateVariables["/_graph2"].stateValues.graphicalDescendants - .length, - ).eq(0); - expect( - stateVariables["/_graph3"].stateValues.graphicalDescendants - .length, - ).eq(0); - expect( - stateVariables["/g4"].stateValues.graphicalDescendants.length, - ).eq(0); - }); - - cy.log("make sequence length 1"); - cy.get(cesc2("#/sequenceCount") + " textarea").type( - "{end}{backspace}1{enter}", - { force: true }, - ); - cy.get(cesc2("#/sequenceCount2")).should("contain.text", "1"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let coords1Anchor = cesc2( - "#" + - stateVariables["/_collect1"].replacements[0].componentName, - ); - let coords2Anchor = cesc2( - "#" + - stateVariables["/_collect1"].replacements[1].componentName, - ); - - cy.get(cesc2("#/_p1")) - .find(coords1Anchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−1,1)"); - }); - cy.get(cesc2("#/_p1")) - .find(coords2Anchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,−1)"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_graph1"].stateValues.graphicalDescendants - .length, - ).eq(2); - expect( - stateVariables["/_graph2"].stateValues.graphicalDescendants - .length, - ).eq(2); - expect( - stateVariables["/_graph3"].stateValues.graphicalDescendants - .length, - ).eq(2); - expect( - stateVariables["/g4"].stateValues.graphicalDescendants - .length, - ).eq(2); - expect(stateVariables["/a/_point1"].stateValues.coords).eqls([ - "vector", - -1, - 1, - ]); - expect(stateVariables["/q/_point1"].stateValues.coords).eqls([ - "vector", - 1, - -1, - ]); - expect( - stateVariables["/copymap1/a/_point1"].stateValues.coords, - ).eqls(["vector", -1, 1]); - expect( - stateVariables["/copymap2/q/_point1"].stateValues.coords, - ).eqls(["vector", 1, -1]); - expect( - stateVariables["/copymap1b/a/_point1"].stateValues.coords, - ).eqls(["vector", -1, 1]); - expect( - stateVariables["/copymap2b/q/_point1"].stateValues.coords, - ).eqls(["vector", 1, -1]); - expect(stateVariables["/g4/a/_point1"].stateValues.coords).eqls( - ["vector", -1, 1], - ); - expect(stateVariables["/g4/q/_point1"].stateValues.coords).eqls( - ["vector", 1, -1], - ); - }); - }); - - cy.log("make sequence length 0 again"); - cy.get(cesc2("#/sequenceCount") + " textarea").type( - "{end}{backspace}0{enter}", - { force: true }, - ); - cy.get(cesc2("#/sequenceCount2")).should("contain.text", "0"); - - cy.get(cesc2("#/_p1")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_graph1"].stateValues.graphicalDescendants - .length, - ).eq(0); - expect( - stateVariables["/_graph2"].stateValues.graphicalDescendants - .length, - ).eq(0); - expect( - stateVariables["/_graph3"].stateValues.graphicalDescendants - .length, - ).eq(0); - expect( - stateVariables["/g4"].stateValues.graphicalDescendants.length, - ).eq(0); - }); - - cy.log("make sequence length 2"); - cy.get(cesc2("#/sequenceCount") + " textarea").type( - "{end}{backspace}2{enter}", - { force: true }, - ); - cy.get(cesc2("#/sequenceCount2")).should("contain.text", "2"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let coords1Anchor = cesc2( - "#" + - stateVariables["/_collect1"].replacements[0].componentName, - ); - let coords2Anchor = cesc2( - "#" + - stateVariables["/_collect1"].replacements[1].componentName, - ); - let coords3Anchor = cesc2( - "#" + - stateVariables["/_collect1"].replacements[2].componentName, - ); - let coords4Anchor = cesc2( - "#" + - stateVariables["/_collect1"].replacements[3].componentName, - ); - - cy.get(cesc2("#/_p1")) - .find(coords1Anchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−1,1)"); - }); - cy.get(cesc2("#/_p1")) - .find(coords2Anchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−2,2)"); - }); - cy.get(cesc2("#/_p1")) - .find(coords3Anchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,−1)"); - }); - cy.get(cesc2("#/_p1")) - .find(coords4Anchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,−2)"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_graph1"].stateValues.graphicalDescendants - .length, - ).eq(4); - expect( - stateVariables["/_graph2"].stateValues.graphicalDescendants - .length, - ).eq(4); - expect( - stateVariables["/_graph3"].stateValues.graphicalDescendants - .length, - ).eq(4); - expect( - stateVariables["/g4"].stateValues.graphicalDescendants - .length, - ).eq(4); - expect(stateVariables["/a/_point1"].stateValues.coords).eqls([ - "vector", - -1, - 1, - ]); - expect(stateVariables["/q/_point1"].stateValues.coords).eqls([ - "vector", - 1, - -1, - ]); - expect( - stateVariables["/copymap1/a/_point1"].stateValues.coords, - ).eqls(["vector", -1, 1]); - expect( - stateVariables["/copymap2/q/_point1"].stateValues.coords, - ).eqls(["vector", 1, -1]); - expect( - stateVariables["/copymap1b/a/_point1"].stateValues.coords, - ).eqls(["vector", -1, 1]); - expect( - stateVariables["/copymap2b/q/_point1"].stateValues.coords, - ).eqls(["vector", 1, -1]); - expect(stateVariables["/g4/a/_point1"].stateValues.coords).eqls( - ["vector", -1, 1], - ); - expect(stateVariables["/g4/q/_point1"].stateValues.coords).eqls( - ["vector", 1, -1], - ); - expect(stateVariables["/b/_point1"].stateValues.coords).eqls([ - "vector", - -2, - 2, - ]); - expect(stateVariables["/r/_point1"].stateValues.coords).eqls([ - "vector", - 2, - -2, - ]); - expect( - stateVariables["/copymap1/b/_point1"].stateValues.coords, - ).eqls(["vector", -2, 2]); - expect( - stateVariables["/copymap2/r/_point1"].stateValues.coords, - ).eqls(["vector", 2, -2]); - expect( - stateVariables["/copymap1b/b/_point1"].stateValues.coords, - ).eqls(["vector", -2, 2]); - expect( - stateVariables["/copymap2b/r/_point1"].stateValues.coords, - ).eqls(["vector", 2, -2]); - expect(stateVariables["/g4/b/_point1"].stateValues.coords).eqls( - ["vector", -2, 2], - ); - expect(stateVariables["/g4/r/_point1"].stateValues.coords).eqls( - ["vector", 2, -2], - ); - }); - }); - - cy.log("change limits"); - cy.get(cesc2("#/sequenceFrom") + " textarea").type( - "{end}{backspace}3{enter}", - { force: true }, - ); - cy.get(cesc2("#/sequenceTo") + " textarea").type( - "{end}{backspace}5{enter}", - { force: true }, - ); - cy.get(cesc2("#/sequenceTo2")).should("contain.text", "5"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let coords1Anchor = cesc2( - "#" + - stateVariables["/_collect1"].replacements[0].componentName, - ); - let coords2Anchor = cesc2( - "#" + - stateVariables["/_collect1"].replacements[1].componentName, - ); - let coords3Anchor = cesc2( - "#" + - stateVariables["/_collect1"].replacements[2].componentName, - ); - let coords4Anchor = cesc2( - "#" + - stateVariables["/_collect1"].replacements[3].componentName, - ); - - cy.get(cesc2("#/_p1")) - .find(coords1Anchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−3,9)"); - }); - cy.get(cesc2("#/_p1")) - .find(coords2Anchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−5,15)"); - }); - cy.get(cesc2("#/_p1")) - .find(coords3Anchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,−9)"); - }); - cy.get(cesc2("#/_p1")) - .find(coords4Anchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,−15)"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_graph1"].stateValues.graphicalDescendants - .length, - ).eq(4); - expect( - stateVariables["/_graph2"].stateValues.graphicalDescendants - .length, - ).eq(4); - expect( - stateVariables["/_graph3"].stateValues.graphicalDescendants - .length, - ).eq(4); - expect( - stateVariables["/g4"].stateValues.graphicalDescendants - .length, - ).eq(4); - expect(stateVariables["/a/_point1"].stateValues.coords).eqls([ - "vector", - -3, - 9, - ]); - expect(stateVariables["/q/_point1"].stateValues.coords).eqls([ - "vector", - 3, - -9, - ]); - expect( - stateVariables["/copymap1/a/_point1"].stateValues.coords, - ).eqls(["vector", -3, 9]); - expect( - stateVariables["/copymap2/q/_point1"].stateValues.coords, - ).eqls(["vector", 3, -9]); - expect( - stateVariables["/copymap1b/a/_point1"].stateValues.coords, - ).eqls(["vector", -3, 9]); - expect( - stateVariables["/copymap2b/q/_point1"].stateValues.coords, - ).eqls(["vector", 3, -9]); - expect(stateVariables["/g4/a/_point1"].stateValues.coords).eqls( - ["vector", -3, 9], - ); - expect(stateVariables["/g4/q/_point1"].stateValues.coords).eqls( - ["vector", 3, -9], - ); - expect(stateVariables["/b/_point1"].stateValues.coords).eqls([ - "vector", - -5, - 15, - ]); - expect(stateVariables["/r/_point1"].stateValues.coords).eqls([ - "vector", - 5, - -15, - ]); - expect( - stateVariables["/copymap1/b/_point1"].stateValues.coords, - ).eqls(["vector", -5, 15]); - expect( - stateVariables["/copymap2/r/_point1"].stateValues.coords, - ).eqls(["vector", 5, -15]); - expect( - stateVariables["/copymap1b/b/_point1"].stateValues.coords, - ).eqls(["vector", -5, 15]); - expect( - stateVariables["/copymap2b/r/_point1"].stateValues.coords, - ).eqls(["vector", 5, -15]); - expect(stateVariables["/g4/b/_point1"].stateValues.coords).eqls( - ["vector", -5, 15], - ); - expect(stateVariables["/g4/r/_point1"].stateValues.coords).eqls( - ["vector", 5, -15], - ); - }); - }); - - cy.log("make sequence length 0 again"); - cy.get(cesc2("#/sequenceCount") + " textarea").type( - "{end}{backspace}0{enter}", - { force: true }, - ); - cy.get(cesc2("#/sequenceCount2")).should("contain.text", "0"); - - cy.get(cesc2("#/_p1")) - .invoke("text") - .then((text) => { - expect(text.trim()).equal(""); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_graph1"].stateValues.graphicalDescendants - .length, - ).eq(0); - expect( - stateVariables["/_graph2"].stateValues.graphicalDescendants - .length, - ).eq(0); - expect( - stateVariables["/_graph3"].stateValues.graphicalDescendants - .length, - ).eq(0); - expect( - stateVariables["/g4"].stateValues.graphicalDescendants.length, - ).eq(0); - }); - - cy.log("make sequence length 3"); - cy.get(cesc2("#/sequenceCount") + " textarea").type( - "{end}{backspace}3{enter}", - { force: true }, - ); - cy.get(cesc2("#/sequenceCount2")).should("contain.text", "3"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let coords1Anchor = cesc2( - "#" + - stateVariables["/_collect1"].replacements[0].componentName, - ); - let coords2Anchor = cesc2( - "#" + - stateVariables["/_collect1"].replacements[1].componentName, - ); - let coords3Anchor = cesc2( - "#" + - stateVariables["/_collect1"].replacements[2].componentName, - ); - let coords4Anchor = cesc2( - "#" + - stateVariables["/_collect1"].replacements[3].componentName, - ); - let coords5Anchor = cesc2( - "#" + - stateVariables["/_collect1"].replacements[4].componentName, - ); - let coords6Anchor = cesc2( - "#" + - stateVariables["/_collect1"].replacements[5].componentName, - ); - - cy.get(cesc2("#/_p1")) - .find(coords1Anchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−3,9)"); - }); - cy.get(cesc2("#/_p1")) - .find(coords2Anchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−4,12)"); - }); - cy.get(cesc2("#/_p1")) - .find(coords3Anchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−5,15)"); - }); - cy.get(cesc2("#/_p1")) - .find(coords4Anchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,−9)"); - }); - cy.get(cesc2("#/_p1")) - .find(coords5Anchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(4,−12)"); - }); - cy.get(cesc2("#/_p1")) - .find(coords6Anchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,−15)"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_graph1"].stateValues.graphicalDescendants - .length, - ).eq(6); - expect( - stateVariables["/_graph2"].stateValues.graphicalDescendants - .length, - ).eq(6); - expect( - stateVariables["/_graph3"].stateValues.graphicalDescendants - .length, - ).eq(6); - expect( - stateVariables["/g4"].stateValues.graphicalDescendants - .length, - ).eq(6); - expect(stateVariables["/a/_point1"].stateValues.coords).eqls([ - "vector", - -3, - 9, - ]); - expect(stateVariables["/q/_point1"].stateValues.coords).eqls([ - "vector", - 3, - -9, - ]); - expect( - stateVariables["/copymap1/a/_point1"].stateValues.coords, - ).eqls(["vector", -3, 9]); - expect( - stateVariables["/copymap2/q/_point1"].stateValues.coords, - ).eqls(["vector", 3, -9]); - expect( - stateVariables["/copymap1b/a/_point1"].stateValues.coords, - ).eqls(["vector", -3, 9]); - expect( - stateVariables["/copymap2b/q/_point1"].stateValues.coords, - ).eqls(["vector", 3, -9]); - expect(stateVariables["/g4/a/_point1"].stateValues.coords).eqls( - ["vector", -3, 9], - ); - expect(stateVariables["/g4/q/_point1"].stateValues.coords).eqls( - ["vector", 3, -9], - ); - expect(stateVariables["/b/_point1"].stateValues.coords).eqls([ - "vector", - -4, - 12, - ]); - expect(stateVariables["/r/_point1"].stateValues.coords).eqls([ - "vector", - 4, - -12, - ]); - expect( - stateVariables["/copymap1/b/_point1"].stateValues.coords, - ).eqls(["vector", -4, 12]); - expect( - stateVariables["/copymap2/r/_point1"].stateValues.coords, - ).eqls(["vector", 4, -12]); - expect( - stateVariables["/copymap1b/b/_point1"].stateValues.coords, - ).eqls(["vector", -4, 12]); - expect( - stateVariables["/copymap2b/r/_point1"].stateValues.coords, - ).eqls(["vector", 4, -12]); - expect(stateVariables["/g4/b/_point1"].stateValues.coords).eqls( - ["vector", -4, 12], - ); - expect(stateVariables["/g4/r/_point1"].stateValues.coords).eqls( - ["vector", 4, -12], - ); - expect(stateVariables["/c/_point1"].stateValues.coords).eqls([ - "vector", - -5, - 15, - ]); - expect(stateVariables["/s/_point1"].stateValues.coords).eqls([ - "vector", - 5, - -15, - ]); - expect( - stateVariables["/copymap1/c/_point1"].stateValues.coords, - ).eqls(["vector", -5, 15]); - expect( - stateVariables["/copymap2/s/_point1"].stateValues.coords, - ).eqls(["vector", 5, -15]); - expect( - stateVariables["/copymap1b/c/_point1"].stateValues.coords, - ).eqls(["vector", -5, 15]); - expect( - stateVariables["/copymap2b/s/_point1"].stateValues.coords, - ).eqls(["vector", 5, -15]); - expect(stateVariables["/g4/c/_point1"].stateValues.coords).eqls( - ["vector", -5, 15], - ); - expect(stateVariables["/g4/s/_point1"].stateValues.coords).eqls( - ["vector", 5, -15], - ); - }); - }); - }); - - it("map points to adapt to math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Number of points:

-

Step size:

- - - - - - - - - - $number.value{assignNames="number2"} - $step.value{assignNames="step2"} - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); //wait for window to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].activeChildren.length).eq(0); - }); - - cy.get(cesc2("#/number") + " textarea").type("10{enter}", { - force: true, - }); - cy.get(cesc2("#/number2")).should("contain.text", "10"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].activeChildren.length).eq(0); - }); - - cy.get(cesc2("#/step") + " textarea").type("1{enter}", { force: true }); - cy.get(cesc2("#/step2")).should("contain.text", "1"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].activeChildren.length).eq(10); - for (let i = 0; i < 10; i++) { - let j = i + 2; - expect( - stateVariables[ - stateVariables["/_math1"].activeChildren[i] - .componentName - ].stateValues.value, - ).eqls(["vector", j, ["apply", "sin", j]]); - } - }); - - cy.get(cesc2("#/number") + " textarea").type( - "{end}{backspace}{backspace}20{enter}", - { force: true }, - ); - cy.get(cesc2("#/number2")).should("contain.text", "20"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].activeChildren.length).eq(20); - for (let i = 0; i < 20; i++) { - let j = i + 2; - expect( - stateVariables[ - stateVariables["/_math1"].activeChildren[i] - .componentName - ].stateValues.value, - ).eqls(["vector", j, ["apply", "sin", j]]); - } - }); - - cy.get(cesc2("#/step") + " textarea").type( - "{end}{backspace}0.5{enter}", - { - force: true, - }, - ); - cy.get(cesc2("#/step2")).should("contain.text", "0.5"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].activeChildren.length).eq(20); - for (let i = 0; i < 20; i++) { - let j = 2 + i * 0.5; - if (Number.isInteger(j)) { - expect( - stateVariables[ - stateVariables["/_math1"].activeChildren[i] - .componentName - ].stateValues.value, - ).eqls(["vector", j, ["apply", "sin", j]]); - } else { - let val = - stateVariables[ - stateVariables["/_math1"].activeChildren[i] - .componentName - ].stateValues.value; - expect(val[0]).eq("vector"); - expect(val[1]).eq(j); - expect(val[2]).closeTo(Math.sin(j), 1e14); - } - } - }); - - cy.get(cesc2("#/number") + " textarea").type( - "{end}{backspace}{backspace}10{enter}", - { force: true }, - ); - cy.get(cesc2("#/number2")).should("contain.text", "10"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].activeChildren.length).eq(10); - for (let i = 0; i < 10; i++) { - let j = 2 + i * 0.5; - if (Number.isInteger(j)) { - expect( - stateVariables[ - stateVariables["/_math1"].activeChildren[i] - .componentName - ].stateValues.value, - ).eqls(["vector", j, ["apply", "sin", j]]); - } else { - let val = - stateVariables[ - stateVariables["/_math1"].activeChildren[i] - .componentName - ].stateValues.value; - expect(val[0]).eq("vector"); - expect(val[1]).eq(j); - expect(val[2]).closeTo(Math.sin(j), 1e14); - } - } - }); - - cy.get(cesc2("#/step") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}{enter}", - { force: true }, - ); - cy.get(cesc2("#/step2")).should("contain.text", "\uff3f"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].activeChildren.length).eq(0); - }); - - cy.get(cesc2("#/number") + " textarea").type( - "{end}{backspace}{backspace}5{enter}", - { force: true }, - ); - cy.get(cesc2("#/number2")).should("contain.text", "5"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].activeChildren.length).eq(0); - }); - - cy.get(cesc2("#/step") + " textarea").type("-3{enter}", { - force: true, - }); - cy.get(cesc2("#/step2")).should("contain.text", `${nInDOM(-3)}`); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_math1"].activeChildren.length).eq(5); - for (let i = 0; i < 5; i++) { - let j = 2 - i * 3; - expect( - stateVariables[ - stateVariables["/_math1"].activeChildren[i] - .componentName - ].stateValues.value, - ).eqls(["vector", j, ["apply", "sin", j]]); - } - }); - }); - - it("map inside sources of map", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Number of points:

- - - - - - - - - - - - $m1 - - - - p1a: $p1{name="p1a"}, - p1b: $(p1/pt{name="p1b"}), - p2a: $p2{name="p2a"}, - p2b: $(p2/pt{name="p2b"}), - p3a: $p3{name="p3a"}, - p3b: $(p3/pt{name="p3b"}), - - q1a: $q1{name="q1a"}, - q1b: $(q1/pt{name="q1b"}), - q2a: $q2{name="q2a"}, - q2b: $(q2/pt{name="q2b"}), - q3a: $q3{name="q3a"}, - q3b: $(q3/pt{name="q3b"}), - -

$number.value{assignNames="number2"}

- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); //wait for window to load - - cy.get(cesc2("#/p1/pt")).should("not.exist"); - cy.get(cesc2("#/p1a/pt")).should("not.exist"); - cy.get(cesc2("#/p1b")).should("not.exist"); - cy.get(cesc2("#/p2/pt")).should("not.exist"); - cy.get(cesc2("#/p2a/pt")).should("not.exist"); - cy.get(cesc2("#/p2b")).should("not.exist"); - cy.get(cesc2("#/p3/pt")).should("not.exist"); - cy.get(cesc2("#/p3a/pt")).should("not.exist"); - cy.get(cesc2("#/p3b")).should("not.exist"); - - cy.get(cesc2("#/q1/pt")).should("not.exist"); - cy.get(cesc2("#/q1a/pt")).should("not.exist"); - cy.get(cesc2("#/q1b")).should("not.exist"); - cy.get(cesc2("#/q2/pt")).should("not.exist"); - cy.get(cesc2("#/q2a/pt")).should("not.exist"); - cy.get(cesc2("#/q2b")).should("not.exist"); - cy.get(cesc2("#/q3/pt")).should("not.exist"); - cy.get(cesc2("#/q3a/pt")).should("not.exist"); - cy.get(cesc2("#/q3b")).should("not.exist"); - - cy.log("set number to be 2"); - cy.get(cesc2("#/number") + " textarea").type( - "{end}{backspace}2{enter}", - { - force: true, - }, - ); - cy.get(cesc2("#/number")).should("contain.text", "2"); - - cy.get(cesc2("#/p1/pt")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,2)"); - }); - cy.get(cesc2("#/p1a/pt")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,2)"); - }); - cy.get(cesc2("#/p1b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,2)"); - }); - - cy.get(cesc2("#/p2/pt")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,4)"); - }); - cy.get(cesc2("#/p2a/pt")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,4)"); - }); - cy.get(cesc2("#/p2b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,4)"); - }); - - cy.get(cesc2("#/p3/pt")).should("not.exist"); - cy.get(cesc2("#/p3a/pt")).should("not.exist"); - cy.get(cesc2("#/p3b")).should("not.exist"); - - cy.get(cesc2("#/q1/pt")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,4)"); - }); - cy.get(cesc2("#/q1a/pt")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,4)"); - }); - cy.get(cesc2("#/q1b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,4)"); - }); - - cy.get(cesc2("#/q2/pt")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(4,16)"); - }); - cy.get(cesc2("#/q2a/pt")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(4,16)"); - }); - cy.get(cesc2("#/q2b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(4,16)"); - }); - - cy.get(cesc2("#/q3/pt")).should("not.exist"); - cy.get(cesc2("#/q3a/pt")).should("not.exist"); - cy.get(cesc2("#/q3b")).should("not.exist"); - - cy.log("set number to be 1"); - cy.get(cesc2("#/number") + " textarea").type( - "{end}{backspace}1{enter}", - { - force: true, - }, - ); - cy.get(cesc2("#/number")).should("contain.text", "1"); - - cy.get(cesc2("#/p1/pt")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,2)"); - }); - cy.get(cesc2("#/p1a/pt")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,2)"); - }); - cy.get(cesc2("#/p1b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,2)"); - }); - - cy.get(cesc2("#/p2/pt")).should("not.exist"); - cy.get(cesc2("#/p2a/pt")).should("not.exist"); - cy.get(cesc2("#/p2b")).should("not.exist"); - cy.get(cesc2("#/p3/pt")).should("not.exist"); - cy.get(cesc2("#/p3a/pt")).should("not.exist"); - cy.get(cesc2("#/p3b")).should("not.exist"); - - cy.get(cesc2("#/q1/pt")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,4)"); - }); - cy.get(cesc2("#/q1a/pt")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,4)"); - }); - cy.get(cesc2("#/q1b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,4)"); - }); - - cy.get(cesc2("#/q2/pt")).should("not.exist"); - cy.get(cesc2("#/q2a/pt")).should("not.exist"); - cy.get(cesc2("#/q2b")).should("not.exist"); - cy.get(cesc2("#/q3/pt")).should("not.exist"); - cy.get(cesc2("#/q3a/pt")).should("not.exist"); - cy.get(cesc2("#/q3b")).should("not.exist"); - - cy.log("set number to be 3"); - cy.get(cesc2("#/number") + " textarea").type( - "{end}{backspace}3{enter}", - { - force: true, - }, - ); - cy.get(cesc2("#/number")).should("contain.text", "3"); - - cy.get(cesc2("#/p1/pt")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,2)"); - }); - cy.get(cesc2("#/p1a/pt")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,2)"); - }); - cy.get(cesc2("#/p1b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,2)"); - }); - - cy.get(cesc2("#/p2/pt")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,4)"); - }); - cy.get(cesc2("#/p2a/pt")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,4)"); - }); - cy.get(cesc2("#/p2b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(2,4)"); - }); - - cy.get(cesc2("#/p3/pt")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,6)"); - }); - cy.get(cesc2("#/p3a/pt")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,6)"); - }); - cy.get(cesc2("#/p3b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,6)"); - }); - - cy.get(cesc2("#/q1/pt")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,4)"); - }); - cy.get(cesc2("#/q1a/pt")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,4)"); - }); - cy.get(cesc2("#/q1b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,4)"); - }); - - cy.get(cesc2("#/q2/pt")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(4,16)"); - }); - cy.get(cesc2("#/q2a/pt")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(4,16)"); - }); - cy.get(cesc2("#/q2b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(4,16)"); - }); - - cy.get(cesc2("#/q3/pt")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(9,36)"); - }); - cy.get(cesc2("#/q3a/pt")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(9,36)"); - }); - cy.get(cesc2("#/q3b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(9,36)"); - }); - - cy.log("set number back to zero"); - cy.get(cesc2("#/number") + " textarea").type( - "{end}{backspace}0{enter}", - { - force: true, - }, - ); - cy.get(cesc2("#/number")).should("contain.text", "0"); - - cy.get(cesc2("#/p1/pt")).should("not.exist"); - cy.get(cesc2("#/p1a/pt")).should("not.exist"); - cy.get(cesc2("#/p1b")).should("not.exist"); - cy.get(cesc2("#/p2/pt")).should("not.exist"); - cy.get(cesc2("#/p2a/pt")).should("not.exist"); - cy.get(cesc2("#/p2b")).should("not.exist"); - cy.get(cesc2("#/p3/pt")).should("not.exist"); - cy.get(cesc2("#/p3a/pt")).should("not.exist"); - cy.get(cesc2("#/p3b")).should("not.exist"); - - cy.get(cesc2("#/q1/pt")).should("not.exist"); - cy.get(cesc2("#/q1a/pt")).should("not.exist"); - cy.get(cesc2("#/q1b")).should("not.exist"); - cy.get(cesc2("#/q2/pt")).should("not.exist"); - cy.get(cesc2("#/q2a/pt")).should("not.exist"); - cy.get(cesc2("#/q2b")).should("not.exist"); - cy.get(cesc2("#/q3/pt")).should("not.exist"); - cy.get(cesc2("#/q3a/pt")).should("not.exist"); - cy.get(cesc2("#/q3b")).should("not.exist"); - - cy.log("set number back to 1"); - cy.get(cesc2("#/number") + " textarea").type( - "{end}{backspace}1{enter}", - { - force: true, - }, - ); - cy.get(cesc2("#/number")).should("contain.text", "1"); - - cy.get(cesc2("#/p1/pt")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,2)"); - }); - cy.get(cesc2("#/p1a/pt")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,2)"); - }); - cy.get(cesc2("#/p1b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,2)"); - }); - - cy.get(cesc2("#/p2/pt")).should("not.exist"); - cy.get(cesc2("#/p2a/pt")).should("not.exist"); - cy.get(cesc2("#/p2b")).should("not.exist"); - cy.get(cesc2("#/p3/pt")).should("not.exist"); - cy.get(cesc2("#/p3a/pt")).should("not.exist"); - cy.get(cesc2("#/p3b")).should("not.exist"); - - cy.get(cesc2("#/q1/pt")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,4)"); - }); - cy.get(cesc2("#/q1a/pt")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,4)"); - }); - cy.get(cesc2("#/q1b")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,4)"); - }); - - cy.get(cesc2("#/q2/pt")).should("not.exist"); - cy.get(cesc2("#/q2a/pt")).should("not.exist"); - cy.get(cesc2("#/q2b")).should("not.exist"); - cy.get(cesc2("#/q3/pt")).should("not.exist"); - cy.get(cesc2("#/q3a/pt")).should("not.exist"); - cy.get(cesc2("#/q3b")).should("not.exist"); - }); - - it("can override fixed of source index", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - redyellow - - - - redyellow - - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); //wait for window to load - - cy.get(cesc2("#/a/ind")).should("have.text", "1"); - cy.get(cesc2("#/b/ind")).should("have.text", "2"); - cy.get(cesc2("#/c/ind")).should("have.text", "1"); - cy.get(cesc2("#/d/ind")).should("have.text", "2"); - - cy.get(cesc2("#/a/_mathinput1") + " textarea").type( - "{end}{backspace}3{enter}", - { force: true }, - ); - cy.get(cesc2("#/b/_mathinput1") + " textarea").type( - "{end}{backspace}4{enter}", - { force: true }, - ); - cy.get(cesc2("#/c/_mathinput1") + " textarea").type( - "{end}{backspace}5{enter}", - { force: true }, - ); - cy.get(cesc2("#/d/_mathinput1") + " textarea").type( - "{end}{backspace}6{enter}", - { force: true }, - ); - - cy.get(cesc2("#/d/ind")).should("have.text", "6"); - cy.get(cesc2("#/a/ind")).should("have.text", "1"); - cy.get(cesc2("#/b/ind")).should("have.text", "2"); - cy.get(cesc2("#/c/ind")).should("have.text", "5"); - - cy.get(cesc2("#/a/_mathinput1") + " textarea").type("{end}x{enter}", { - force: true, - }); - cy.get(cesc2("#/b/_mathinput1") + " textarea").type("{end}x{enter}", { - force: true, - }); - cy.get(cesc2("#/c/_mathinput1") + " textarea").type("{end}x{enter}", { - force: true, - }); - cy.get(cesc2("#/d/_mathinput1") + " textarea").type("{end}x{enter}", { - force: true, - }); - - cy.get(cesc2("#/d/ind")).should("have.text", "NaN"); - cy.get(cesc2("#/a/ind")).should("have.text", "1"); - cy.get(cesc2("#/b/ind")).should("have.text", "2"); - cy.get(cesc2("#/c/ind")).should("have.text", "NaN"); - - cy.get(cesc2("#/a/_mathinput1") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}7{enter}", - { force: true }, - ); - cy.get(cesc2("#/b/_mathinput1") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}8{enter}", - { force: true }, - ); - cy.get(cesc2("#/c/_mathinput1") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}9{enter}", - { force: true }, - ); - cy.get(cesc2("#/d/_mathinput1") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}10{enter}", - { force: true }, - ); - - cy.get(cesc2("#/d/ind")).should("have.text", "10"); - cy.get(cesc2("#/a/ind")).should("have.text", "1"); - cy.get(cesc2("#/b/ind")).should("have.text", "2"); - cy.get(cesc2("#/c/ind")).should("have.text", "9"); - }); - - it("maps hide dynamically", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - -

Length of map 1:

-

Length of map 2:

- -

map 1: - - -

-

map 2: - - -

- -

- $h1.value{assignNames="h1a"} - $h2.value{assignNames="h2a"} - $n1.value{assignNames="n1a"} - $n2.value{assignNames="n2a"} -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/m1")).should( - "have.text", - "map 1: hi1, hi2, hi3, hi4 ", - ); - cy.get(cesc("#\\/m2")).should("have.text", "map 2: "); - - cy.get(cesc("#\\/n1") + " textarea").type("{end}{backspace}6{enter}", { - force: true, - }); - cy.get(cesc("#\\/n2") + " textarea").type("{end}{backspace}6{enter}", { - force: true, - }); - cy.get(cesc("#\\/n2a")).should("contain.text", "6"); - cy.get(cesc("#\\/n1a")).should("contain.text", "6"); - - cy.get(cesc("#\\/m1")).should( - "have.text", - "map 1: hi1, hi2, hi3, hi4, hi5, hi6 ", - ); - cy.get(cesc("#\\/m2")).should("have.text", "map 2: "); - - cy.get(cesc("#\\/h1")).click(); - cy.get(cesc("#\\/h2")).click(); - cy.get(cesc("#\\/h2a")).should("contain.text", "false"); - cy.get(cesc("#\\/h1a")).should("contain.text", "true"); - - cy.get(cesc("#\\/m1")).should("have.text", "map 1: "); - cy.get(cesc("#\\/m2")).should( - "have.text", - "map 2: hi1, hi2, hi3, hi4, hi5, hi6 ", - ); - - cy.get(cesc("#\\/n1") + " textarea").type("{end}{backspace}8{enter}", { - force: true, - }); - cy.get(cesc("#\\/n2") + " textarea").type("{end}{backspace}8{enter}", { - force: true, - }); - cy.get(cesc("#\\/n2a")).should("contain.text", "8"); - cy.get(cesc("#\\/n1a")).should("contain.text", "8"); - - cy.get(cesc("#\\/m1")).should("have.text", "map 1: "); - cy.get(cesc("#\\/m2")).should( - "have.text", - "map 2: hi1, hi2, hi3, hi4, hi5, hi6, hi7, hi8 ", - ); - - cy.get(cesc("#\\/h1")).click(); - cy.get(cesc("#\\/h2")).click(); - cy.get(cesc("#\\/h2a")).should("contain.text", "true"); - cy.get(cesc("#\\/h1a")).should("contain.text", "false"); - - cy.get(cesc("#\\/m1")).should( - "have.text", - "map 1: hi1, hi2, hi3, hi4, hi5, hi6, hi7, hi8 ", - ); - cy.get(cesc("#\\/m2")).should("have.text", "map 2: "); - - cy.get(cesc("#\\/n1") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - cy.get(cesc("#\\/n2") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - cy.get(cesc("#\\/n2a")).should("contain.text", "3"); - cy.get(cesc("#\\/n1a")).should("contain.text", "3"); - - cy.get(cesc("#\\/m1")).should("have.text", "map 1: hi1, hi2, hi3 "); - cy.get(cesc("#\\/m2")).should("have.text", "map 2: "); - - cy.get(cesc("#\\/h1")).click(); - cy.get(cesc("#\\/h2")).click(); - cy.get(cesc("#\\/h2a")).should("contain.text", "false"); - cy.get(cesc("#\\/h1a")).should("contain.text", "true"); - - cy.get(cesc("#\\/m1")).should("have.text", "map 1: "); - cy.get(cesc("#\\/m2")).should("have.text", "map 2: hi1, hi2, hi3 "); - - cy.get(cesc("#\\/n1") + " textarea").type("{end}{backspace}4{enter}", { - force: true, - }); - cy.get(cesc("#\\/n2") + " textarea").type("{end}{backspace}4{enter}", { - force: true, - }); - cy.get(cesc("#\\/n2a")).should("contain.text", "4"); - cy.get(cesc("#\\/n1a")).should("contain.text", "4"); - - cy.get(cesc("#\\/m1")).should("have.text", "map 1: "); - cy.get(cesc("#\\/m2")).should( - "have.text", - "map 2: hi1, hi2, hi3, hi4 ", - ); - }); - - it("map displays as list by default, single number in template", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

-

- - - - -

-

- - - - -

-

$default

-

$nocommas

-

$withcommas

-

$default{asList="false"}

-

$withcommas{asList="false"}

-

$nocommas{asList="true"}

-

-

-

-

-

-

-

-

-

- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - - cy.get(cesc2("#/default")) - .invoke("text") - .then((text) => - expect(text.replace(/, \s*/g, ", ").trim()).eq( - "1, 4, 9, 16, 25, 36, 49, 64, 81, 100", - ), - ); - cy.get(cesc2("#/pdefault2")) - .invoke("text") - .then((text) => - expect(text.replace(/, \s*/g, ", ").trim()).eq( - "1, 4, 9, 16, 25, 36, 49, 64, 81, 100", - ), - ); - cy.get(cesc2("#/pdefault4")) - .invoke("text") - .then((text) => - expect(text.replace(/, \s*/g, ", ").trim()).eq( - "1, 4, 9, 16, 25, 36, 49, 64, 81, 100", - ), - ); - cy.get(cesc2("#/pdefault5")) - .invoke("text") - .then((text) => - expect(text.replace(/, \s*/g, ", ").trim()).eq( - "1, 4, 9, 16, 25, 36, 49, 64, 81, 100", - ), - ); - cy.get(cesc2("#/nocommas")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+/g, " ").trim()).eq( - "1 4 9 16 25 36 49 64 81 100", - ), - ); - cy.get(cesc2("#/pnocommas2")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+/g, " ").trim()).eq( - "1 4 9 16 25 36 49 64 81 100", - ), - ); - cy.get(cesc2("#/pnocommas3")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+/g, " ").trim()).eq( - "1 4 9 16 25 36 49 64 81 100", - ), - ); - cy.get(cesc2("#/pnocommas3a")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+/g, " ").trim()).eq( - "1 4 9 16 25 36 49 64 81 100", - ), - ); - cy.get(cesc2("#/pnocommas4")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+/g, " ").trim()).eq( - "1 4 9 16 25 36 49 64 81 100", - ), - ); - cy.get(cesc2("#/pnocommas5")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+/g, " ").trim()).eq( - "1 4 9 16 25 36 49 64 81 100", - ), - ); - cy.get(cesc2("#/pnocommas6")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+/g, " ").trim()).eq( - "1 4 9 16 25 36 49 64 81 100", - ), - ); - cy.get(cesc2("#/pnocommas6a")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+/g, " ").trim()).eq( - "1 4 9 16 25 36 49 64 81 100", - ), - ); - - cy.get(cesc2("#/withcommas")) - .invoke("text") - .then((text) => - expect(text.replace(/, \s*/g, ", ").trim()).eq( - "1, 4, 9, 16, 25, 36, 49, 64, 81, 100", - ), - ); - cy.get(cesc2("#/pwithcommas2")) - .invoke("text") - .then((text) => - expect(text.replace(/, \s*/g, ", ").trim()).eq( - "1, 4, 9, 16, 25, 36, 49, 64, 81, 100", - ), - ); - cy.get(cesc2("#/pwithcommas3")) - .invoke("text") - .then((text) => - expect(text.replace(/, \s*/g, ", ").trim()).eq( - "1, 4, 9, 16, 25, 36, 49, 64, 81, 100", - ), - ); - cy.get(cesc2("#/pwithcommas4")) - .invoke("text") - .then((text) => - expect(text.replace(/, \s*/g, ", ").trim()).eq( - "1, 4, 9, 16, 25, 36, 49, 64, 81, 100", - ), - ); - cy.get(cesc2("#/pwithcommas5")) - .invoke("text") - .then((text) => - expect(text.replace(/, \s*/g, ", ").trim()).eq( - "1, 4, 9, 16, 25, 36, 49, 64, 81, 100", - ), - ); - cy.get(cesc2("#/pwithcommas6")) - .invoke("text") - .then((text) => - expect(text.replace(/, \s*/g, ", ").trim()).eq( - "1, 4, 9, 16, 25, 36, 49, 64, 81, 100", - ), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/pdefault"].stateValues.text - .replace(/, \s*/g, ", ") - .trim(), - ).eq("1, 4, 9, 16, 25, 36, 49, 64, 81, 100"); - expect( - stateVariables["/pdefault2"].stateValues.text - .replace(/, \s*/g, ", ") - .trim(), - ).eq("1, 4, 9, 16, 25, 36, 49, 64, 81, 100"); - expect( - stateVariables["/pdefault4"].stateValues.text - .replace(/, \s*/g, ", ") - .trim(), - ).eq("1, 4, 9, 16, 25, 36, 49, 64, 81, 100"); - expect( - stateVariables["/pdefault5"].stateValues.text - .replace(/, \s*/g, ", ") - .trim(), - ).eq("1, 4, 9, 16, 25, 36, 49, 64, 81, 100"); - expect( - stateVariables["/pnocommas"].stateValues.text - .replace(/\s+/g, " ") - .trim(), - ).eq("1 4 9 16 25 36 49 64 81 100"); - expect( - stateVariables["/pnocommas2"].stateValues.text - .replace(/\s+/g, " ") - .trim(), - ).eq("1 4 9 16 25 36 49 64 81 100"); - expect( - stateVariables["/pnocommas3"].stateValues.text - .replace(/\s+/g, " ") - .trim(), - ).eq("1 4 9 16 25 36 49 64 81 100"); - expect( - stateVariables["/pnocommas3a"].stateValues.text - .replace(/\s+/g, " ") - .trim(), - ).eq("1 4 9 16 25 36 49 64 81 100"); - expect( - stateVariables["/pnocommas4"].stateValues.text - .replace(/\s+/g, " ") - .trim(), - ).eq("1 4 9 16 25 36 49 64 81 100"); - expect( - stateVariables["/pnocommas5"].stateValues.text - .replace(/\s+/g, " ") - .trim(), - ).eq("1 4 9 16 25 36 49 64 81 100"); - expect( - stateVariables["/pnocommas6"].stateValues.text - .replace(/\s+/g, " ") - .trim(), - ).eq("1 4 9 16 25 36 49 64 81 100"); - expect( - stateVariables["/pnocommas6a"].stateValues.text - .replace(/\s+/g, " ") - .trim(), - ).eq("1 4 9 16 25 36 49 64 81 100"); - expect( - stateVariables["/pwithcommas"].stateValues.text - .replace(/, \s*/g, ", ") - .trim(), - ).eq("1, 4, 9, 16, 25, 36, 49, 64, 81, 100"); - expect( - stateVariables["/pwithcommas2"].stateValues.text - .replace(/, \s*/g, ", ") - .trim(), - ).eq("1, 4, 9, 16, 25, 36, 49, 64, 81, 100"); - expect( - stateVariables["/pwithcommas3"].stateValues.text - .replace(/, \s*/g, ", ") - .trim(), - ).eq("1, 4, 9, 16, 25, 36, 49, 64, 81, 100"); - expect( - stateVariables["/pwithcommas4"].stateValues.text - .replace(/, \s*/g, ", ") - .trim(), - ).eq("1, 4, 9, 16, 25, 36, 49, 64, 81, 100"); - expect( - stateVariables["/pwithcommas5"].stateValues.text - .replace(/, \s*/g, ", ") - .trim(), - ).eq("1, 4, 9, 16, 25, 36, 49, 64, 81, 100"); - expect( - stateVariables["/pwithcommas6"].stateValues.text - .replace(/, \s*/g, ", ") - .trim(), - ).eq("1, 4, 9, 16, 25, 36, 49, 64, 81, 100"); - }); - }); - - it("map displays as list by default, number and string in template", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

-

- - - - -

-

- - - - -

-

$default

-

$nocommas

-

$withcommas

-

$default{asList="false"}

-

$withcommas{asList="false"}

-

$nocommas{asList="true"}

-

-

-

-

-

-

-

-

-

- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - - // Note: we do not remove whitespace that has a following commas, - // as we want to test that the whitespace before a comma is removed. - cy.get(cesc2("#/default")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+(?!,)/g, " ").trim()).eq( - "1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x", - ), - ); - cy.get(cesc2("#/pdefault2")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+(?!,)/g, " ").trim()).eq( - "1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x", - ), - ); - cy.get(cesc2("#/pdefault4")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+(?!,)/g, " ").trim()).eq( - "1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x", - ), - ); - cy.get(cesc2("#/pdefault5")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+(?!,)/g, " ").trim()).eq( - "1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x", - ), - ); - cy.get(cesc2("#/nocommas")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+/g, " ").trim()).eq( - "1 x 4 x 9 x 16 x 25 x 36 x 49 x 64 x 81 x 100 x", - ), - ); - cy.get(cesc2("#/pnocommas2")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+/g, " ").trim()).eq( - "1 x 4 x 9 x 16 x 25 x 36 x 49 x 64 x 81 x 100 x", - ), - ); - cy.get(cesc2("#/pnocommas3")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+/g, " ").trim()).eq( - "1 x 4 x 9 x 16 x 25 x 36 x 49 x 64 x 81 x 100 x", - ), - ); - cy.get(cesc2("#/pnocommas3a")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+/g, " ").trim()).eq( - "1 x 4 x 9 x 16 x 25 x 36 x 49 x 64 x 81 x 100 x", - ), - ); - cy.get(cesc2("#/pnocommas4")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+/g, " ").trim()).eq( - "1 x 4 x 9 x 16 x 25 x 36 x 49 x 64 x 81 x 100 x", - ), - ); - cy.get(cesc2("#/pnocommas5")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+/g, " ").trim()).eq( - "1 x 4 x 9 x 16 x 25 x 36 x 49 x 64 x 81 x 100 x", - ), - ); - cy.get(cesc2("#/pnocommas6")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+/g, " ").trim()).eq( - "1 x 4 x 9 x 16 x 25 x 36 x 49 x 64 x 81 x 100 x", - ), - ); - cy.get(cesc2("#/pnocommas6a")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+/g, " ").trim()).eq( - "1 x 4 x 9 x 16 x 25 x 36 x 49 x 64 x 81 x 100 x", - ), - ); - - cy.get(cesc2("#/withcommas")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+(?!,)/g, " ").trim()).eq( - "1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x", - ), - ); - cy.get(cesc2("#/pwithcommas2")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+(?!,)/g, " ").trim()).eq( - "1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x", - ), - ); - cy.get(cesc2("#/pwithcommas3")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+(?!,)/g, " ").trim()).eq( - "1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x", - ), - ); - cy.get(cesc2("#/pwithcommas4")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+(?!,)/g, " ").trim()).eq( - "1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x", - ), - ); - cy.get(cesc2("#/pwithcommas5")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+(?!,)/g, " ").trim()).eq( - "1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x", - ), - ); - cy.get(cesc2("#/pwithcommas6")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+(?!,)/g, " ").trim()).eq( - "1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x", - ), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/pdefault"].stateValues.text - .replace(/\s+(?!,)/g, " ") - .trim(), - ).eq("1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x"); - expect( - stateVariables["/pdefault2"].stateValues.text - .replace(/\s+(?!,)/g, " ") - .trim(), - ).eq("1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x"); - expect( - stateVariables["/pdefault4"].stateValues.text - .replace(/\s+(?!,)/g, " ") - .trim(), - ).eq("1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x"); - expect( - stateVariables["/pdefault5"].stateValues.text - .replace(/\s+(?!,)/g, " ") - .trim(), - ).eq("1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x"); - expect( - stateVariables["/pnocommas"].stateValues.text - .replace(/\s+/g, " ") - .trim(), - ).eq("1 x 4 x 9 x 16 x 25 x 36 x 49 x 64 x 81 x 100 x"); - expect( - stateVariables["/pnocommas2"].stateValues.text - .replace(/\s+/g, " ") - .trim(), - ).eq("1 x 4 x 9 x 16 x 25 x 36 x 49 x 64 x 81 x 100 x"); - expect( - stateVariables["/pnocommas3"].stateValues.text - .replace(/\s+/g, " ") - .trim(), - ).eq("1 x 4 x 9 x 16 x 25 x 36 x 49 x 64 x 81 x 100 x"); - expect( - stateVariables["/pnocommas3a"].stateValues.text - .replace(/\s+/g, " ") - .trim(), - ).eq("1 x 4 x 9 x 16 x 25 x 36 x 49 x 64 x 81 x 100 x"); - expect( - stateVariables["/pnocommas4"].stateValues.text - .replace(/\s+/g, " ") - .trim(), - ).eq("1 x 4 x 9 x 16 x 25 x 36 x 49 x 64 x 81 x 100 x"); - expect( - stateVariables["/pnocommas5"].stateValues.text - .replace(/\s+/g, " ") - .trim(), - ).eq("1 x 4 x 9 x 16 x 25 x 36 x 49 x 64 x 81 x 100 x"); - expect( - stateVariables["/pnocommas6"].stateValues.text - .replace(/\s+/g, " ") - .trim(), - ).eq("1 x 4 x 9 x 16 x 25 x 36 x 49 x 64 x 81 x 100 x"); - expect( - stateVariables["/pnocommas6a"].stateValues.text - .replace(/\s+/g, " ") - .trim(), - ).eq("1 x 4 x 9 x 16 x 25 x 36 x 49 x 64 x 81 x 100 x"); - expect( - stateVariables["/pwithcommas"].stateValues.text - .replace(/\s+(?!,)/g, " ") - .trim(), - ).eq("1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x"); - expect( - stateVariables["/pwithcommas2"].stateValues.text - .replace(/\s+(?!,)/g, " ") - .trim(), - ).eq("1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x"); - expect( - stateVariables["/pwithcommas3"].stateValues.text - .replace(/\s+(?!,)/g, " ") - .trim(), - ).eq("1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x"); - expect( - stateVariables["/pwithcommas4"].stateValues.text - .replace(/\s+(?!,)/g, " ") - .trim(), - ).eq("1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x"); - expect( - stateVariables["/pwithcommas5"].stateValues.text - .replace(/\s+(?!,)/g, " ") - .trim(), - ).eq("1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x"); - expect( - stateVariables["/pwithcommas6"].stateValues.text - .replace(/\s+(?!,)/g, " ") - .trim(), - ).eq("1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x"); - }); - }); - - it("map displays as list by default, number, string and math in template", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

-

- - - - -

-

- - - - -

-

$default

-

$nocommas

-

$withcommas

-

$default{asList="false"}

-

$withcommas{asList="false"}

-

$nocommas{asList="true"}

-

-

-

-

-

-

-

-

-

- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); - - // make sure Mathjax has run - cy.get(cesc2("#/default") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - - // Note: we do not remove whitespace that has a following commas, - // as we want to test that the whitespace before a comma is removed. - - // Note 2: to check relationship between math and commas, - // we will grab the entire text, which includes 3 copies of math right now - // (subject to change if MathJax changes how their different formats work) - cy.get(cesc2("#/default")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+(?!,)/g, " ").trim()).eq( - "1 xxx, 4 xxx, 9 xxx, 16 xxx, 25 xxx, 36 xxx, 49 xxx, 64 xxx, 81 xxx, 100 xxx", - ), - ); - cy.get(cesc2("#/pdefault2")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+(?!,)/g, " ").trim()).eq( - "1 xxx, 4 xxx, 9 xxx, 16 xxx, 25 xxx, 36 xxx, 49 xxx, 64 xxx, 81 xxx, 100 xxx", - ), - ); - cy.get(cesc2("#/pdefault4")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+(?!,)/g, " ").trim()).eq( - "1 xxx, 4 xxx, 9 xxx, 16 xxx, 25 xxx, 36 xxx, 49 xxx, 64 xxx, 81 xxx, 100 xxx", - ), - ); - cy.get(cesc2("#/pdefault5")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+(?!,)/g, " ").trim()).eq( - "1 xxx, 4 xxx, 9 xxx, 16 xxx, 25 xxx, 36 xxx, 49 xxx, 64 xxx, 81 xxx, 100 xxx", - ), - ); - cy.get(cesc2("#/nocommas")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+/g, " ").trim()).eq( - "1 xxx 4 xxx 9 xxx 16 xxx 25 xxx 36 xxx 49 xxx 64 xxx 81 xxx 100 xxx", - ), - ); - cy.get(cesc2("#/pnocommas2")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+/g, " ").trim()).eq( - "1 xxx 4 xxx 9 xxx 16 xxx 25 xxx 36 xxx 49 xxx 64 xxx 81 xxx 100 xxx", - ), - ); - cy.get(cesc2("#/pnocommas3")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+/g, " ").trim()).eq( - "1 xxx 4 xxx 9 xxx 16 xxx 25 xxx 36 xxx 49 xxx 64 xxx 81 xxx 100 xxx", - ), - ); - cy.get(cesc2("#/pnocommas3a")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+/g, " ").trim()).eq( - "1 xxx 4 xxx 9 xxx 16 xxx 25 xxx 36 xxx 49 xxx 64 xxx 81 xxx 100 xxx", - ), - ); - cy.get(cesc2("#/pnocommas4")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+/g, " ").trim()).eq( - "1 xxx 4 xxx 9 xxx 16 xxx 25 xxx 36 xxx 49 xxx 64 xxx 81 xxx 100 xxx", - ), - ); - cy.get(cesc2("#/pnocommas5")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+/g, " ").trim()).eq( - "1 xxx 4 xxx 9 xxx 16 xxx 25 xxx 36 xxx 49 xxx 64 xxx 81 xxx 100 xxx", - ), - ); - cy.get(cesc2("#/pnocommas6")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+/g, " ").trim()).eq( - "1 xxx 4 xxx 9 xxx 16 xxx 25 xxx 36 xxx 49 xxx 64 xxx 81 xxx 100 xxx", - ), - ); - cy.get(cesc2("#/pnocommas6a")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+/g, " ").trim()).eq( - "1 xxx 4 xxx 9 xxx 16 xxx 25 xxx 36 xxx 49 xxx 64 xxx 81 xxx 100 xxx", - ), - ); - - cy.get(cesc2("#/withcommas")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+(?!,)/g, " ").trim()).eq( - "1 xxx, 4 xxx, 9 xxx, 16 xxx, 25 xxx, 36 xxx, 49 xxx, 64 xxx, 81 xxx, 100 xxx", - ), - ); - cy.get(cesc2("#/pwithcommas2")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+(?!,)/g, " ").trim()).eq( - "1 xxx, 4 xxx, 9 xxx, 16 xxx, 25 xxx, 36 xxx, 49 xxx, 64 xxx, 81 xxx, 100 xxx", - ), - ); - cy.get(cesc2("#/pwithcommas3")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+(?!,)/g, " ").trim()).eq( - "1 xxx, 4 xxx, 9 xxx, 16 xxx, 25 xxx, 36 xxx, 49 xxx, 64 xxx, 81 xxx, 100 xxx", - ), - ); - cy.get(cesc2("#/pwithcommas4")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+(?!,)/g, " ").trim()).eq( - "1 xxx, 4 xxx, 9 xxx, 16 xxx, 25 xxx, 36 xxx, 49 xxx, 64 xxx, 81 xxx, 100 xxx", - ), - ); - cy.get(cesc2("#/pwithcommas5")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+(?!,)/g, " ").trim()).eq( - "1 xxx, 4 xxx, 9 xxx, 16 xxx, 25 xxx, 36 xxx, 49 xxx, 64 xxx, 81 xxx, 100 xxx", - ), - ); - cy.get(cesc2("#/pwithcommas6")) - .invoke("text") - .then((text) => - expect(text.replace(/\s+(?!,)/g, " ").trim()).eq( - "1 xxx, 4 xxx, 9 xxx, 16 xxx, 25 xxx, 36 xxx, 49 xxx, 64 xxx, 81 xxx, 100 xxx", - ), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/pdefault"].stateValues.text - .replace(/\s+(?!,)/g, " ") - .trim(), - ).eq("1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x"); - expect( - stateVariables["/pdefault2"].stateValues.text - .replace(/\s+(?!,)/g, " ") - .trim(), - ).eq("1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x"); - expect( - stateVariables["/pdefault4"].stateValues.text - .replace(/\s+(?!,)/g, " ") - .trim(), - ).eq("1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x"); - expect( - stateVariables["/pdefault5"].stateValues.text - .replace(/\s+(?!,)/g, " ") - .trim(), - ).eq("1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x"); - expect( - stateVariables["/pnocommas"].stateValues.text - .replace(/\s+/g, " ") - .trim(), - ).eq("1 x 4 x 9 x 16 x 25 x 36 x 49 x 64 x 81 x 100 x"); - expect( - stateVariables["/pnocommas2"].stateValues.text - .replace(/\s+/g, " ") - .trim(), - ).eq("1 x 4 x 9 x 16 x 25 x 36 x 49 x 64 x 81 x 100 x"); - expect( - stateVariables["/pnocommas3"].stateValues.text - .replace(/\s+/g, " ") - .trim(), - ).eq("1 x 4 x 9 x 16 x 25 x 36 x 49 x 64 x 81 x 100 x"); - expect( - stateVariables["/pnocommas3a"].stateValues.text - .replace(/\s+/g, " ") - .trim(), - ).eq("1 x 4 x 9 x 16 x 25 x 36 x 49 x 64 x 81 x 100 x"); - expect( - stateVariables["/pnocommas4"].stateValues.text - .replace(/\s+/g, " ") - .trim(), - ).eq("1 x 4 x 9 x 16 x 25 x 36 x 49 x 64 x 81 x 100 x"); - expect( - stateVariables["/pnocommas5"].stateValues.text - .replace(/\s+/g, " ") - .trim(), - ).eq("1 x 4 x 9 x 16 x 25 x 36 x 49 x 64 x 81 x 100 x"); - expect( - stateVariables["/pnocommas6"].stateValues.text - .replace(/\s+/g, " ") - .trim(), - ).eq("1 x 4 x 9 x 16 x 25 x 36 x 49 x 64 x 81 x 100 x"); - expect( - stateVariables["/pnocommas6a"].stateValues.text - .replace(/\s+/g, " ") - .trim(), - ).eq("1 x 4 x 9 x 16 x 25 x 36 x 49 x 64 x 81 x 100 x"); - expect( - stateVariables["/pwithcommas"].stateValues.text - .replace(/\s+(?!,)/g, " ") - .trim(), - ).eq("1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x"); - expect( - stateVariables["/pwithcommas2"].stateValues.text - .replace(/\s+(?!,)/g, " ") - .trim(), - ).eq("1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x"); - expect( - stateVariables["/pwithcommas3"].stateValues.text - .replace(/\s+(?!,)/g, " ") - .trim(), - ).eq("1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x"); - expect( - stateVariables["/pwithcommas4"].stateValues.text - .replace(/\s+(?!,)/g, " ") - .trim(), - ).eq("1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x"); - expect( - stateVariables["/pwithcommas5"].stateValues.text - .replace(/\s+(?!,)/g, " ") - .trim(), - ).eq("1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x"); - expect( - stateVariables["/pwithcommas6"].stateValues.text - .replace(/\s+(?!,)/g, " ") - .trim(), - ).eq("1 x, 4 x, 9 x, 16 x, 25 x, 36 x, 49 x, 64 x, 81 x, 100 x"); - }); +describe("Map Tag Tests", function () { + beforeEach(() => { + cy.clearIndexedDB(); + cy.visit("/"); }); it("map will not display as list if has block components", () => { @@ -5551,162 +30,4 @@ describe("Map Tag Tests", function () { cy.get(cesc2("#/_document1")).should("contain.text", "Hello 3"); cy.get(cesc2("#/_document1")).should("not.contain.text", ","); }); - - it("map will display as list if has components with canBeInList", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - -

-

- - -

-

- - -

-

- - -

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,1)"); - cy.get(cesc2("#/p1") + " .mjx-mrow") - .eq(2) - .should("have.text", "(2,4)"); - cy.get(cesc2("#/p1") + " .mjx-mrow") - .eq(4) - .should("have.text", "(3,9)"); - cy.get(cesc2("#/p1")).should("contain.text", "), ("); - - cy.get(cesc2("#/p2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,1)"); - cy.get(cesc2("#/p2") + " .mjx-mrow") - .eq(2) - .should("have.text", "(2,4)"); - cy.get(cesc2("#/p2") + " .mjx-mrow") - .eq(4) - .should("have.text", "(3,9)"); - cy.get(cesc2("#/p2")).should("contain.text", "), ("); - - cy.get(cesc2("#/p3") + " .mjx-mrow") - .eq(0) - .should("have.text", "y=1"); - cy.get(cesc2("#/p3") + " .mjx-mrow") - .eq(1) - .should("have.text", "y=2"); - cy.get(cesc2("#/p3") + " .mjx-mrow") - .eq(2) - .should("have.text", "y=3"); - cy.get(cesc2("#/p3")).should("contain.text", "1, y"); - cy.get(cesc2("#/p3")).should("contain.text", "2, y"); - - cy.get(cesc2("#/p4") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - cy.get(cesc2("#/p4") + " .mjx-mrow") - .eq(1) - .should("have.text", "4"); - cy.get(cesc2("#/p4") + " .mjx-mrow") - .eq(2) - .should("have.text", "6"); - cy.get(cesc2("#/p4")).should("contain.text", "2, 4"); - cy.get(cesc2("#/p4")).should("contain.text", "4, 6"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/p1"].stateValues.text).eq( - "( 1, 1 ), ( 2, 4 ), ( 3, 9 )", - ); - expect(stateVariables["/p2"].stateValues.text).eq( - "( 1, 1 ), ( 2, 4 ), ( 3, 9 )", - ); - expect(stateVariables["/p3"].stateValues.text).eq( - "y = 1, y = 2, y = 3", - ); - expect(stateVariables["/p4"].stateValues.text).eq("2, 4, 6"); - }); - }); - - it("properly create unique name to avoid duplicate names", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/n1")).should("have.text", "1"); - cy.get(cesc("#\\/n2")).should("have.text", "2"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1a = stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements.filter((s) => s.componentType)[1].componentName; - let n2a = stateVariables[ - stateVariables["/_map1"].replacements[1].componentName - ].replacements.filter((s) => s.componentType)[1].componentName; - - expect(stateVariables["/n1"].stateValues.value).eq(1); - expect(stateVariables[n1a].stateValues.value).eq(10); - expect(stateVariables["/n2"].stateValues.value).eq(2); - expect(stateVariables[n2a].stateValues.value).eq(20); - }); - }); - - it("bug for isResponse and parallel is fixed", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/p1")).should("have.text", "hi 1"); - cy.get(cesc("#\\/p2")).should("have.text", "hi 2"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - expect(stateVariables["/p1"].stateValues.isResponse).eq(true); - expect(stateVariables["/p2"].stateValues.isResponse).eq(true); - }); - }); }); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/mathinputgraph.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/mathinputgraph.cy.js deleted file mode 100644 index 3872fc3c2..000000000 --- a/packages/test-cypress/cypress/e2e/tagSpecific/mathinputgraph.cy.js +++ /dev/null @@ -1,575 +0,0 @@ -import me from "math-expressions"; -import { cesc, cesc2 } from "@doenet/utils"; - -describe("MathInput Graph Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("mathinputs specifying point", () => { - // two mathinputs specifying the x and y coordinate of a single point - // demonstrates two-way data binding - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - ($x.value,$y.value) - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let coordsAnchor = cesc2( - "#" + stateVariables["/coords"].replacements[0].componentName, - ); - - cy.log("Test values displayed in browser"); - cy.get(coordsAnchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,2)"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/x"].stateValues.value).is.eq(1); - expect(stateVariables["/y"].stateValues.value).is.eq(2); - expect(stateVariables["/_point1"].stateValues.xs[0]).is.eq(1); - expect(stateVariables["/_point1"].stateValues.xs[1]).is.eq(2); - }); - - cy.log("Enter -3 for x"); - cy.get(cesc("#\\/x") + " textarea").type( - "{end}{backspace}-3{enter}", - { - force: true, - }, - ); - cy.get(coordsAnchor).should("contain.text", "(−3,2)"); - - cy.log("Test values displayed in browser"); - cy.get(coordsAnchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−3,2)"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - me - .fromAst(stateVariables["/x"].stateValues.value) - .evaluate_to_constant(), - ).to.eq(-3); - expect(stateVariables["/y"].stateValues.value).is.eq(2); - expect( - me - .fromAst(stateVariables["/_point1"].stateValues.xs[0]) - .evaluate_to_constant(), - ).to.eq(-3); - expect(stateVariables["/_point1"].stateValues.xs[1]).is.eq(2); - }); - - cy.log("Enter -4 for y"); - cy.get(cesc("#\\/y") + " textarea").type( - "{end}{backspace}-4{enter}", - { - force: true, - }, - ); - cy.get(coordsAnchor).should("contain.text", "(−3,−4)"); - - cy.log("Test values displayed in browser"); - cy.get(coordsAnchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−3,−4)"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - me - .fromAst(stateVariables["/x"].stateValues.value) - .evaluate_to_constant(), - ).to.eq(-3); - expect( - me - .fromAst(stateVariables["/y"].stateValues.value) - .evaluate_to_constant(), - ).to.eq(-4); - expect( - me - .fromAst(stateVariables["/_point1"].stateValues.xs[0]) - .evaluate_to_constant(), - ).to.eq(-3); - expect( - me - .fromAst(stateVariables["/_point1"].stateValues.xs[1]) - .evaluate_to_constant(), - ).to.eq(-4); - }); - - cy.log(`move point to (5,-6)`); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 5, y: -6 }, - }); - let stateVariables = await win.returnAllStateVariables1(); - expect( - me - .fromAst(stateVariables["/x"].stateValues.value) - .evaluate_to_constant(), - ).to.eq(5); - expect( - me - .fromAst(stateVariables["/y"].stateValues.value) - .evaluate_to_constant(), - ).to.eq(-6); - expect(stateVariables["/_point1"].stateValues.xs[0]).eq(5); - expect(stateVariables["/_point1"].stateValues.xs[1]).eq(-6); - }); - - cy.log("Test values displayed in browser"); - cy.get(coordsAnchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,−6)"); - }); - }); - }); - - it("mathinput specifying point -- non-invertible x", () => { - // x-coordinate is the square of the first mathinput - // therefore, cannot invert from x-coordinate to mathinput - // so that cannot change x-coordinate directly by dragging point - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - ($x.value^2,$y.value) - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let coordsAnchor = cesc2( - "#" + stateVariables["/coords"].replacements[0].componentName, - ); - - cy.log("Test values displayed in browser"); - cy.get(coordsAnchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(9,2)"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/x"].stateValues.value).is.eq(3); - expect(stateVariables["/y"].stateValues.value).is.eq(2); - expect(stateVariables["/_point1"].stateValues.xs[0]).is.eq(9); - expect(stateVariables["/_point1"].stateValues.xs[1]).is.eq(2); - }); - - cy.log("Enter -1.2 for x"); - cy.get(cesc("#\\/x") + " textarea").type( - "{end}{backspace}-1.2{enter}", - { - force: true, - }, - ); - cy.get(coordsAnchor).should("contain.text", "(1.44,2)"); - - cy.log("Test values displayed in browser"); - cy.get(coordsAnchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1.44,2)"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - me - .fromAst(stateVariables["/x"].stateValues.value) - .evaluate_to_constant(), - ).to.eq(-1.2); - expect(stateVariables["/y"].stateValues.value).is.eq(2); - expect( - me - .fromAst(stateVariables["/_point1"].stateValues.xs[0]) - .evaluate_to_constant(), - ).to.eq(1.44); - expect(stateVariables["/_point1"].stateValues.xs[1]).is.eq(2); - }); - - cy.log(`try to move point to (5,6)`); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 5, y: 6 }, - }); - let stateVariables = await win.returnAllStateVariables1(); - expect( - me - .fromAst(stateVariables["/x"].stateValues.value) - .evaluate_to_constant(), - ).to.eq(-1.2); - expect( - me - .fromAst(stateVariables["/y"].stateValues.value) - .evaluate_to_constant(), - ).to.eq(6); - expect(stateVariables["/_point1"].stateValues.xs[0]).eq(1.44); - expect(stateVariables["/_point1"].stateValues.xs[1]).eq(6); - }); - - cy.log("Test values displayed in browser"); - cy.get(coordsAnchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1.44,6)"); - }); - }); - }); - - it("mathinput specifying point -- product", () => { - // x-coordinate of a point is product of mathinputs - // Since cannot determine both factors from the product - // the transformation is non-invertible - // and cannot directly change the x-coordinate of point by dragging - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - ($a.value$b.value, -7) - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let coordsAnchor = cesc2( - "#" + stateVariables["/coords"].replacements[0].componentName, - ); - - cy.log("Test values displayed in browser"); - cy.get(coordsAnchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−6,−7)"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - me - .fromAst(stateVariables["/a"].stateValues.value) - .evaluate_to_constant(), - ).is.eq(-3); - expect( - me - .fromAst(stateVariables["/b"].stateValues.value) - .evaluate_to_constant(), - ).is.eq(2); - expect( - me - .fromAst(stateVariables["/_point1"].stateValues.xs[0]) - .evaluate_to_constant(), - ).is.eq(-6); - expect( - me - .fromAst(stateVariables["/_point1"].stateValues.xs[1]) - .evaluate_to_constant(), - ).is.eq(-7); - }); - - cy.log("Enter -1.5 for a"); - cy.get(cesc("#\\/a") + " textarea").type( - "{end}{backspace}{backspace}-1.5{enter}", - { force: true }, - ); - cy.get(coordsAnchor).should("contain.text", "(−3,−7)"); - - cy.log("Test values displayed in browser"); - cy.get(coordsAnchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−3,−7)"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - me - .fromAst(stateVariables["/a"].stateValues.value) - .evaluate_to_constant(), - ).is.eq(-1.5); - expect( - me - .fromAst(stateVariables["/b"].stateValues.value) - .evaluate_to_constant(), - ).is.eq(2); - expect( - me - .fromAst(stateVariables["/_point1"].stateValues.xs[0]) - .evaluate_to_constant(), - ).is.eq(-3); - expect( - me - .fromAst(stateVariables["/_point1"].stateValues.xs[1]) - .evaluate_to_constant(), - ).is.eq(-7); - }); - - cy.log(`try to move point to (5,6)`); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 5, y: 6 }, - }); - let stateVariables = await win.returnAllStateVariables1(); - expect( - me - .fromAst(stateVariables["/a"].stateValues.value) - .evaluate_to_constant(), - ).is.eq(-1.5); - expect( - me - .fromAst(stateVariables["/b"].stateValues.value) - .evaluate_to_constant(), - ).is.eq(2); - expect( - me - .fromAst(stateVariables["/_point1"].stateValues.xs[0]) - .evaluate_to_constant(), - ).is.eq(-3); - expect( - me - .fromAst(stateVariables["/_point1"].stateValues.xs[1]) - .evaluate_to_constant(), - ).is.eq(6); - }); - - cy.log("Test values displayed in browser"); - cy.get(coordsAnchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−3,6)"); - }); - }); - }); - - it("mathinput specifying point -- product, make invertible", () => { - // x-coordinate of a point is product of mathinputs - // Since one factor is marked with modifyIndirectly=false, - // we leave that factor constant when changing the x-coordinate by dragging - // and modify the other factor to match the new x-coordinate - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - ($a.value, -7) - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let coordsAnchor = cesc2( - "#" + stateVariables["/coords"].replacements[0].componentName, - ); - - cy.log("Test values displayed in browser"); - cy.get(coordsAnchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−6,−7)"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - me - .fromAst(stateVariables["/a"].stateValues.value) - .evaluate_to_constant(), - ).is.eq(-3); - expect( - me - .fromAst(stateVariables["/b"].stateValues.value) - .evaluate_to_constant(), - ).is.eq(2); - expect( - me - .fromAst(stateVariables["/_point1"].stateValues.xs[0]) - .evaluate_to_constant(), - ).is.eq(-6); - expect( - me - .fromAst(stateVariables["/_point1"].stateValues.xs[1]) - .evaluate_to_constant(), - ).is.eq(-7); - }); - - cy.log("Enter -1.5 for a"); - cy.get(cesc("#\\/a") + " textarea").type( - "{end}{backspace}{backspace}-1.5{enter}", - { force: true }, - ); - cy.get(coordsAnchor).should("contain.text", "(−3,−7)"); - - cy.log("Test values displayed in browser"); - cy.get(coordsAnchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−3,−7)"); - }); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - me - .fromAst(stateVariables["/a"].stateValues.value) - .evaluate_to_constant(), - ).is.eq(-1.5); - expect( - me - .fromAst(stateVariables["/b"].stateValues.value) - .evaluate_to_constant(), - ).is.eq(2); - expect( - me - .fromAst(stateVariables["/_point1"].stateValues.xs[0]) - .evaluate_to_constant(), - ).is.eq(-3); - expect( - me - .fromAst(stateVariables["/_point1"].stateValues.xs[1]) - .evaluate_to_constant(), - ).is.eq(-7); - }); - - cy.log(`move point to (5,6)`); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/_point1", - args: { x: 5, y: 6 }, - }); - let stateVariables = await win.returnAllStateVariables1(); - expect( - me - .fromAst(stateVariables["/a"].stateValues.value) - .evaluate_to_constant(), - ).is.eq(2.5); - expect( - me - .fromAst(stateVariables["/b"].stateValues.value) - .evaluate_to_constant(), - ).is.eq(2); - expect( - me - .fromAst(stateVariables["/_point1"].stateValues.xs[0]) - .evaluate_to_constant(), - ).is.eq(5); - expect( - me - .fromAst(stateVariables["/_point1"].stateValues.xs[1]) - .evaluate_to_constant(), - ).is.eq(6); - }); - - cy.log("Test values displayed in browser"); - cy.get(coordsAnchor) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,6)"); - }); - }); - }); -}); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/sampleprimenumbers.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/sampleprimenumbers.cy.js index 6629c0674..e47584d25 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/sampleprimenumbers.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/sampleprimenumbers.cy.js @@ -6,1731 +6,6 @@ describe("SamplePrimeNumbers Tag Tests", function () { cy.visit("/"); }); - it("no parameters, sample random prime number up to 100", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1 -

- - $p2{name="p3"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - - expect(samples.length).eq(50); - - for (let sample of samples) { - expect( - [ - 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, - 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, - ].includes(sample), - ).eq(true); - } - - let copiedSamples = stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("sample five prime numbers up to 20, only maxValue specified", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1 -

- - $p2{name="p3"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(samples.length).eq(50); - - for (let sample of samples) { - expect([2, 3, 5, 7, 11, 13, 17, 19].includes(sample)).eq(true); - } - - let copiedSamples = stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("sample five prime numbers between 50 and 100, only minValue specified", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1 -

- - $p2{name="p3"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(samples.length).eq(50); - - for (let sample of samples) { - expect( - [53, 59, 61, 67, 71, 73, 79, 83, 89, 97].includes(sample), - ).eq(true); - } - - let copiedSamples = stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("sample ten prime numbers betweeen 10,000 and 100,0000", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1 -

- - $p2{name="p3"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(samples.length).eq(50); - - for (let sample of samples) { - expect( - Number.isInteger(sample) && - sample >= 10000 && - sample <= 100000, - ).eq(true); - - let isprime = true; - let sqrtsample = Math.sqrt(sample); - for (let i = 2; i <= sqrtsample; i++) { - if (sample % i === 0) { - isprime = false; - break; - } - } - - expect(isprime).eq(true); - } - - let copiedSamples = stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("sample fifty prime numbers betweeen 1900 and 2000, excluding 1931, 1979, and 1997", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- -

- -

- $samples{name="samples2"} -

- - $p2{name="p3"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables["/samples"].replacements.map( - (y) => stateVariables[y.componentName].stateValues.value, - ); - expect(samples.length).eq(50); - - for (let sample of samples) { - expect( - [ - 1901, 1907, 1913, 1933, 1949, 1951, 1973, 1987, 1993, - 1999, - ].includes(sample), - ).eq(true); - } - - let copiedSamples = stateVariables["/samples2"].replacements.map( - (y) => stateVariables[y.componentName].stateValues.value, - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("sampled number does change dynamically", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

- -

- - - - $exclude -

- -

-

- $numSamples2.value{assignNames="numSamples2a"} -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let sample1numbers, sample2numbers; - let sample1numbersb, sample2numbersb; - let sample1numbersc, sample2numbersc; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - sample1numbers = stateVariables["/sample1"].replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - sample2numbers = stateVariables["/sample2"].replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(sample1numbers.length).eq(50); - expect(sample2numbers.length).eq(180); - - for (let num of sample1numbers) { - expect([2, 3, 5, 7].includes(num)).eq(true); - } - - for (let num of sample2numbers) { - expect([2, 3, 5, 11, 13, 17, 23, 31, 41, 43].includes(num)).eq( - true, - ); - } - }); - - cy.log("Get new samples when change number of samples"); - cy.get(cesc("#\\/numSamples") + " textarea").type( - `{end}{backspace}{backspace}70{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/numSamples2") + " textarea").type( - `{ctrl+home}{shift+end}{backspace}160{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/numSamples2a")).should("contain.text", "160"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - sample1numbersb = stateVariables["/sample1"].replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - sample2numbersb = stateVariables["/sample2"].replacements - .slice( - 0, - stateVariables["/sample2"].replacements.length - - stateVariables["/sample2"].replacementsToWithhold, - ) - .map((x) => stateVariables[x.componentName].stateValues.value); - expect(sample1numbersb.length).eq(70); - expect(sample2numbersb.length).eq(160); - - for (let num of sample1numbersb) { - expect([2, 3, 5, 7].includes(num)).eq(true); - } - - for (let num of sample2numbersb) { - expect([2, 3, 5, 11, 13, 17, 23, 31, 41, 43].includes(num)).eq( - true, - ); - } - - expect(sample1numbersb.slice(0, 10)).not.eqls( - sample1numbers.slice(0, 10), - ); - expect(sample2numbersb.slice(0, 10)).not.eqls( - sample2numbers.slice(0, 10), - ); - }); - - cy.log("Get new samples when change parameters"); - cy.get(cesc("#\\/maxnum") + " textarea").type( - `{end}{backspace}{backspace}20{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/exclude") + " textarea").type( - `{end}, 2, 11, 23, 31, 41{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/ml_exclude")).should("contain.text", "41"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - sample1numbersc = stateVariables["/sample1"].replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - sample2numbersc = stateVariables["/sample2"].replacements - .slice( - 0, - stateVariables["/sample2"].replacements.length - - stateVariables["/sample2"].replacementsToWithhold, - ) - .map((x) => stateVariables[x.componentName].stateValues.value); - expect(sample1numbersc.length).eq(70); - expect(sample2numbersc.length).eq(160); - - for (let num of sample1numbersc) { - expect([2, 3, 5, 7, 11, 13, 17, 19].includes(num)).eq(true); - } - - for (let num of sample2numbersc) { - expect([3, 5, 13, 17, 43].includes(num)).eq(true); - } - - expect(sample1numbersc.slice(0, 10)).not.eqls( - sample1numbersb.slice(0, 10), - ); - expect(sample2numbersc.slice(0, 10)).not.eqls( - sample2numbersb.slice(0, 10), - ); - }); - }); - - it("sampled number doesn't resample in dynamic map", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - How many numbers do you want? -

- - - - - - -

- -

$_map1

-

$_aslist1

- - $p1{name="p4"} - $p2{name="p5"} - $p3{name="p6"} - - $p6{name="p7"} - $p7{name="p8"} - $p8{name="p9"} -

$_mathinput1.value{assignNames="m1"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let samplednumbers = []; - - cy.log("initially nothing"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - }); - - cy.log("sample one number"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}1{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "1"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - samplednumbers.push(n1); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - for (let ind = 0; ind < 1; ind++) { - expect( - stateVariables[ - stateVariables[ - stateVariables["/p1"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p2"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p3"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p4"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p5"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p6"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p7"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p8"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p9"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - } - }); - - cy.log("go back to nothing"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}0{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "0"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - }); - - cy.log("get same number back"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}1{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "1"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - expect(n1).eq(samplednumbers[0]); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - - for (let ind = 0; ind < 1; ind++) { - expect( - stateVariables[ - stateVariables[ - stateVariables["/p1"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p2"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p3"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p4"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p5"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p6"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p7"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p8"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p9"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - } - }); - - cy.log("get two more samples"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}3{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "3"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - let n2 = stateVariables["/b/n"].stateValues.value; - let n3 = stateVariables["/c/n"].stateValues.value; - expect(n1).eq(samplednumbers[0]); - samplednumbers.push(n2); - samplednumbers.push(n3); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - for (let ind = 0; ind < 3; ind++) { - expect( - stateVariables[ - stateVariables[ - stateVariables["/p1"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p2"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p3"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p4"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p5"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p6"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p7"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p8"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p9"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - } - }); - - cy.log("go back to nothing"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}0{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "0"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - }); - - cy.log("get first two numbers back"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}2{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "2"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - let n2 = stateVariables["/b/n"].stateValues.value; - expect(n1).eq(samplednumbers[0]); - expect(n2).eq(samplednumbers[1]); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - - for (let ind = 0; ind < 2; ind++) { - expect( - stateVariables[ - stateVariables[ - stateVariables["/p1"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p2"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p3"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p4"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p5"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p6"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p7"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p8"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p9"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - } - }); - - cy.log("get six total samples"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}6{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "6"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - let n2 = stateVariables["/b/n"].stateValues.value; - let n3 = stateVariables["/c/n"].stateValues.value; - let n4 = stateVariables["/d/n"].stateValues.value; - let n5 = stateVariables["/e/n"].stateValues.value; - let n6 = stateVariables["/f/n"].stateValues.value; - expect(n1).eq(samplednumbers[0]); - expect(n2).eq(samplednumbers[1]); - expect(n3).eq(samplednumbers[2]); - samplednumbers.push(n4); - samplednumbers.push(n5); - samplednumbers.push(n6); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - for (let ind = 0; ind < 6; ind++) { - expect( - stateVariables[ - stateVariables[ - stateVariables["/p1"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p2"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p3"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p4"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p5"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p6"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p7"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p8"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p9"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - } - }); - - cy.log("go back to nothing"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}0{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "0"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - }); - - cy.log("get all six back"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}6{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "6"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - let n2 = stateVariables["/b/n"].stateValues.value; - let n3 = stateVariables["/c/n"].stateValues.value; - let n4 = stateVariables["/d/n"].stateValues.value; - let n5 = stateVariables["/e/n"].stateValues.value; - let n6 = stateVariables["/f/n"].stateValues.value; - expect(n1).eq(samplednumbers[0]); - expect(n2).eq(samplednumbers[1]); - expect(n3).eq(samplednumbers[2]); - expect(n4).eq(samplednumbers[3]); - expect(n5).eq(samplednumbers[4]); - expect(n6).eq(samplednumbers[5]); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - for (let ind = 0; ind < 6; ind++) { - expect( - stateVariables[ - stateVariables[ - stateVariables["/p1"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p2"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p3"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p4"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p5"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p6"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p7"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p8"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p9"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - } - }); - }); - - it("sample single prime number, assign name", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

-

$u{name="u2"}

-

$v{name="v2"}

-

$w{name="w2"}

- `, - }, - "*", - ); - }); - - let options = [83, 89]; - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let u = stateVariables["/u"]; - let u2 = stateVariables["/u2"]; - - expect(options.includes(u.stateValues.value)).eq(true); - expect(u.stateValues.value).eq(u2.stateValues.value); - - let v = stateVariables["/v"]; - let v2 = stateVariables["/v2"]; - expect(options.includes(v.stateValues.value)).eq(true); - expect(v.stateValues.value).eq(v2.stateValues.value); - - let w = stateVariables["/w"]; - let w2 = stateVariables["/w2"]; - expect(options.includes(w.stateValues.value)).eq(true); - expect(w.stateValues.value).eq(w2.stateValues.value); - }); - }); - - it("sample multiple prime numbers, assign names", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- -

-

$u{name="u2"}

-

$v{name="v2"}

-

$w{name="w2"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let results = []; - - for (let ind = 0; ind < 6; ind++) { - cy.get(cesc("#\\/_p1") + " > :nth-child(" + (2 * ind + 4) + ")") - .invoke("text") - .then((text) => { - let num = Number(text); - results[ind] = num; - expect([179, 181, 191, 193, 197, 199].includes(num)); - }); - } - - cy.log("check by name").then(() => { - cy.get(cesc("#\\/u")).should("have.text", results[0]); - cy.get(cesc("#\\/u2")).should("have.text", results[0]); - cy.get(cesc("#\\/v")).should("have.text", results[1]); - cy.get(cesc("#\\/v2")).should("have.text", results[1]); - cy.get(cesc("#\\/w")).should("have.text", results[2]); - cy.get(cesc("#\\/w2")).should("have.text", results[2]); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let u = stateVariables["/u"]; - let u2 = stateVariables["/u2"]; - expect(u.stateValues.value).eq(results[0]); - expect(u2.stateValues.value).eq(results[0]); - - let v = stateVariables["/v"]; - let v2 = stateVariables["/v2"]; - expect(v.stateValues.value).eq(results[1]); - expect(v2.stateValues.value).eq(results[1]); - - let w = stateVariables["/w"]; - let w2 = stateVariables["/w2"]; - expect(w.stateValues.value).eq(results[2]); - expect(w2.stateValues.value).eq(results[2]); - - let s = stateVariables["/s"]; - expect(s.replacements.length).eq(6); - for (let ind = 0; ind < 6; ind++) { - let r = stateVariables[s.replacements[ind].componentName]; - expect(r.stateValues.value).eq(results[ind]); - } - }); - }); - - it("sample multiple prime numbers, assign names, newNamespace", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- -

-

$(s/u{name="u2"})

-

$(s/v{name="v2"})

-

$(s/w{name="w2"})

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let results = []; - - for (let ind = 0; ind < 6; ind++) { - cy.get(cesc("#\\/_p1") + " > :nth-child(" + (2 * ind + 4) + ")") - .invoke("text") - .then((text) => { - let num = Number(text); - results[ind] = num; - expect([179, 181, 191, 193, 197, 199].includes(num)); - }); - } - - cy.log("check by name").then(() => { - cy.get(cesc("#\\/s\\/u")).should("have.text", results[0]); - cy.get(cesc("#\\/u2")).should("have.text", results[0]); - cy.get(cesc("#\\/s\\/v")).should("have.text", results[1]); - cy.get(cesc("#\\/v2")).should("have.text", results[1]); - cy.get(cesc("#\\/s\\/w")).should("have.text", results[2]); - cy.get(cesc("#\\/w2")).should("have.text", results[2]); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let u = stateVariables["/s/u"]; - let u2 = stateVariables["/u2"]; - expect(u.stateValues.value).eq(results[0]); - expect(u2.stateValues.value).eq(results[0]); - - let v = stateVariables["/s/v"]; - let v2 = stateVariables["/v2"]; - expect(v.stateValues.value).eq(results[1]); - expect(v2.stateValues.value).eq(results[1]); - - let w = stateVariables["/s/w"]; - let w2 = stateVariables["/w2"]; - expect(w.stateValues.value).eq(results[2]); - expect(w2.stateValues.value).eq(results[2]); - - let s = stateVariables["/s"]; - expect(s.replacements.length).eq(6); - for (let ind = 0; ind < 6; ind++) { - let r = stateVariables[s.replacements[ind].componentName]; - expect(r.stateValues.value).eq(results[ind]); - } - }); - }); - - it("asList", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let results = []; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - results.push(stateVariables["/u"].stateValues.value); - results.push(stateVariables["/v"].stateValues.value); - results.push(stateVariables["/w"].stateValues.value); - results.push(stateVariables["/x"].stateValues.value); - results.push(stateVariables["/y"].stateValues.value); - - for (let num of results) { - expect([179, 181, 191, 193, 197, 199].includes(num)); - } - cy.get(cesc2("#/_p1")).should("have.text", results.join(", ")); - cy.get(cesc2("#/_p2")).should("have.text", results.join("")); - }); - }); - it(`different numbers when reload page if don't save state`, () => { let doenetML = ` a @@ -1901,198 +176,4 @@ describe("SamplePrimeNumbers Tag Tests", function () { expect(samples2).eqls(samples); }); }); - - it("same numbers for given variant if variantDeterminesSeed", () => { - let doenetML = ` - a -

- - - - -

- - `; - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: 1, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let samples = []; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - samples = stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - - expect(samples.length).eq(100); - - for (let sample of samples) { - expect( - [ - 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, - 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, - ].includes(sample), - ).eq(true); - } - }); - - cy.reload(); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: 1, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples2 = stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - - expect(samples2).eqls(samples); - }); - - cy.reload(); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: 2, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples2 = stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - - expect(samples2.length).eq(100); - - for (let sample of samples2) { - expect( - [ - 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, - 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, - ].includes(sample), - ).eq(true); - } - - expect(samples2).not.eqls(samples); - }); - }); - - it(`resample prime numbers`, () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

, - -

- -

- - -

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let pn1, pn2, pn3; - let pn1b, pn2b, pn3b; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - pn1 = stateVariables["/pn1"].stateValues.value; - pn2 = stateVariables["/pn2"].stateValues.value; - pn3 = stateVariables["/pn3"].stateValues.value; - - expect(pn1).gt(1).lt(1000); - expect(pn2).gt(1).lt(1000); - expect(pn3).gt(1000).lt(10000); - - cy.get(cesc2("#/pn1")).should("have.text", pn1.toString()); - - cy.get(cesc2("#/resamp1")).click(); - - cy.get(cesc2("#/pn1")).should("not.have.text", pn1.toString()); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - pn1b = stateVariables["/pn1"].stateValues.value; - pn2b = stateVariables["/pn2"].stateValues.value; - pn3b = stateVariables["/pn3"].stateValues.value; - - expect(pn1b).gt(1).lt(1000); - expect(pn2b).gt(1).lt(1000); - expect(pn3b).gt(1000).lt(10000); - - expect(pn1b).not.eq(pn1); - expect(pn2b).not.eq(pn2); - expect(pn3b).eq(pn3); - - cy.get(cesc2("#/pn3")).should("have.text", pn3.toString()); - - cy.get(cesc2("#/resamp2")).click(); - - cy.get(cesc2("#/pn3")).should("not.have.text", pn3.toString()); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let pn1c = stateVariables["/pn1"].stateValues.value; - let pn2c = stateVariables["/pn2"].stateValues.value; - let pn3c = stateVariables["/pn3"].stateValues.value; - - expect(pn1c).gt(1).lt(1000); - expect(pn2c).gt(1).lt(1000); - expect(pn3c).gt(1000).lt(10000); - - expect(pn1c).eq(pn1b); - expect(pn2c).eq(pn2b); - expect(pn3c).not.eq(pn3); - }); - }); }); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/samplerandomnumbers.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/samplerandomnumbers.cy.js index 621abefd2..6f39aa32a 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/samplerandomnumbers.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/samplerandomnumbers.cy.js @@ -1,5 +1,4 @@ -import me from "math-expressions"; -import { cesc, cesc2 } from "@doenet/utils"; +import { cesc } from "@doenet/utils"; describe("SampleRandomNumbers Tag Tests", function () { beforeEach(() => { @@ -7,2636 +6,6 @@ describe("SampleRandomNumbers Tag Tests", function () { cy.visit("/"); }); - it("no parameters, sample single uniform random number from 0 to 1", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1 -

- - $p2{name="p3"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(samples.length).eq(400); - - for (let sample of samples) { - expect(sample).gt(0); - expect(sample).lte(1); - } - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(0.5, 0.05); - expect(varX).closeTo(1 / 12, 0.015); - - let firstSample = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSample.stateValues.mean).closeTo(0.5, 1e-10); - expect(firstSample.stateValues.variance).closeTo(1 / 12, 1e-10); - expect(firstSample.stateValues.standardDeviation).closeTo( - Math.sqrt(1 / 12), - 1e-10, - ); - - let copiedSamples = stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - console.log(samples, copiedSamples); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("sample five uniform random numbers from 0 to 8, only to specified", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1 -

- - $p2{name="p3"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(samples.length).eq(400); - - for (let sample of samples) { - expect(sample).gt(0); - expect(sample).lte(8); - } - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(4, 0.5); - expect(varX).closeTo(8 ** 2 / 12, 0.8); - - let firstSample = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSample.stateValues.mean).closeTo(4, 1e-10); - expect(firstSample.stateValues.variance).closeTo( - 8 ** 2 / 12, - 1e-10, - ); - expect(firstSample.stateValues.standardDeviation).closeTo( - Math.sqrt(8 ** 2 / 12), - 1e-10, - ); - - let copiedSamples = stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("sample five uniform random numbers from -5 to -4, only from specified", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1 -

- - $p2{name="p3"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(samples.length).eq(400); - - for (let sample of samples) { - expect(sample).gt(-5); - expect(sample).lte(-4); - } - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(-4.5, 0.05); - expect(varX).closeTo(1 / 12, 0.015); - - let firstSample = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSample.stateValues.mean).closeTo(-4.5, 1e-10); - expect(firstSample.stateValues.variance).closeTo(1 / 12, 1e-10); - expect(firstSample.stateValues.standardDeviation).closeTo( - Math.sqrt(1 / 12), - 1e-10, - ); - - let copiedSamples = stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("sample ten uniform random numbers from -4 to -2", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1 -

- - $p2{name="p3"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(samples.length).eq(400); - - for (let sample of samples) { - expect(sample).gt(-4); - expect(sample).lte(-2); - } - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(-3, 0.5); - expect(varX).closeTo(2 ** 2 / 12, 0.5); - - let firstSample = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSample.stateValues.mean).closeTo(-3, 1e-10); - expect(firstSample.stateValues.variance).closeTo( - 2 ** 2 / 12, - 1e-10, - ); - expect(firstSample.stateValues.standardDeviation).closeTo( - Math.sqrt(2 ** 2 / 12), - 1e-10, - ); - - let copiedSamples = stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("sample ten uniform random numbers from -2 to -4", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1 -

- - $p2{name="p3"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(samples.length).eq(400); - - for (let sample of samples) { - expect(sample).gt(-4); - expect(sample).lte(-2); - } - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(-3, 0.5); - expect(varX).closeTo(2 ** 2 / 12, 0.5); - - let firstSample = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSample.stateValues.mean).closeTo(-3, 1e-10); - expect(firstSample.stateValues.variance).closeTo( - 2 ** 2 / 12, - 1e-10, - ); - expect(firstSample.stateValues.standardDeviation).closeTo( - Math.sqrt(2 ** 2 / 12), - 1e-10, - ); - - let copiedSamples = stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("sample twenty continuous standard normals, no parameters", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1 -

- - $p2{name="p3"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(samples.length).eq(400); - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(0, 0.15); - expect(varX).closeTo(1, 0.3); - - let firstSample = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSample.stateValues.mean).closeTo(0, 1e-10); - expect(firstSample.stateValues.variance).closeTo(1, 1e-10); - expect(firstSample.stateValues.standardDeviation).closeTo( - Math.sqrt(1), - 1e-10, - ); - - let copiedSamples = stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("sample five continuous standard normals, unspecified mean 0, standard deviation 10", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1 -

- - $p2{name="p3"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(samples.length).eq(400); - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(0, 2); - expect(varX).closeTo(100, 25); - - let firstSample = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSample.stateValues.mean).closeTo(0, 1e-10); - expect(firstSample.stateValues.variance).closeTo(100, 1e-10); - expect(firstSample.stateValues.standardDeviation).closeTo( - Math.sqrt(100), - 1e-10, - ); - - let copiedSamples = stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("sample single continuous standard normal, mean -50, unspecified standard deviation 1", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1 -

- - $p2{name="p3"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(samples.length).eq(400); - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(-50, 0.2); - expect(varX).closeTo(1, 0.3); - - let firstSample = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSample.stateValues.mean).closeTo(-50, 1e-10); - expect(firstSample.stateValues.variance).closeTo(1, 1e-10); - expect(firstSample.stateValues.standardDeviation).closeTo( - Math.sqrt(1), - 1e-10, - ); - - let copiedSamples = stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("sample twenty continuous standard normals, mean 100, standard deviation 10", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1 -

- - $p2{name="p3"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(samples.length).eq(400); - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(100, 2); - expect(varX).closeTo(100, 30); - - let firstSample = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSample.stateValues.mean).closeTo(100, 1e-10); - expect(firstSample.stateValues.variance).closeTo(100, 1e-10); - expect(firstSample.stateValues.standardDeviation).closeTo( - Math.sqrt(100), - 1e-10, - ); - - let copiedSamples = stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("sample twenty continuous standard normals, mean -3, variance 0.01", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1 -

- - $p2{name="p3"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(samples.length).eq(400); - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(-3, 0.1); - expect(varX).closeTo(0.01, 0.003); - - let firstSample = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSample.stateValues.mean).closeTo(-3, 1e-10); - expect(firstSample.stateValues.variance).closeTo(0.01, 1e-10); - expect(firstSample.stateValues.standardDeviation).closeTo( - Math.sqrt(0.01), - 1e-10, - ); - - let copiedSamples = stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("sample single discrete uniform, no parameters, integer from 0 to 1", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1 -

- - $p2{name="p3"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(samples.length).eq(400); - - for (let sample of samples) { - expect([0, 1].includes(sample)).eq(true); - } - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(0.5, 0.1); - expect(varX).closeTo((2 ** 2 - 1) / 12, 0.1); - - let firstSample = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSample.stateValues.mean).closeTo(0.5, 1e-10); - expect(firstSample.stateValues.variance).closeTo( - (2 ** 2 - 1) / 12, - 1e-10, - ); - expect(firstSample.stateValues.standardDeviation).closeTo( - Math.sqrt((2 ** 2 - 1) / 12), - 1e-10, - ); - - let copiedSamples = stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("sample single discrete uniform, from 0.5 to 5.5, only to specified", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1 -

- - $p2{name="p3"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(samples.length).eq(400); - - for (let sample of samples) { - expect([0.5, 1.5, 2.5, 3.5, 4.5, 5.5].includes(sample)).eq( - true, - ); - } - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(3, 0.3); - expect(varX).closeTo((6 ** 2 - 1) / 12, 0.5); - - let firstSample = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSample.stateValues.mean).closeTo(3, 1e-10); - expect(firstSample.stateValues.variance).closeTo( - (6 ** 2 - 1) / 12, - 1e-10, - ); - expect(firstSample.stateValues.standardDeviation).closeTo( - Math.sqrt((6 ** 2 - 1) / 12), - 1e-10, - ); - - let copiedSamples = stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("sample single discrete uniform, from 8.5 to 9.5, only from specified", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1 -

- - $p2{name="p3"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(samples.length).eq(400); - - for (let sample of samples) { - expect([8.5, 9.5].includes(sample)).eq(true); - } - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(9, 0.1); - expect(varX).closeTo((2 ** 2 - 1) / 12, 0.05); - - let firstSample = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSample.stateValues.mean).closeTo(9, 1e-10); - expect(firstSample.stateValues.variance).closeTo( - (2 ** 2 - 1) / 12, - 1e-10, - ); - expect(firstSample.stateValues.standardDeviation).closeTo( - Math.sqrt((2 ** 2 - 1) / 12), - 1e-10, - ); - - let copiedSamples = stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("sample five integers from -3 to 5", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1 -

- - $p2{name="p3"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(samples.length).eq(400); - - for (let sample of samples) { - expect([-3, -2, -1, 0, 1, 2, 3, 4, 5].includes(sample)).eq( - true, - ); - } - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(1, 0.5); - expect(varX).closeTo((9 ** 2 - 1) / 12, 1); - - let firstSample = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSample.stateValues.mean).closeTo(1, 1e-10); - expect(firstSample.stateValues.variance).closeTo( - (9 ** 2 - 1) / 12, - 1e-10, - ); - expect(firstSample.stateValues.standardDeviation).closeTo( - Math.sqrt((9 ** 2 - 1) / 12), - 1e-10, - ); - - let copiedSamples = stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("sample five integers from 5 to -3 gives nothing", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1 -

- - $p2{name="p3"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(samples.length).eq(0); - - let copiedSamples = stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("sample 10 odd integers from -3 to 5", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1 -

- - $p2{name="p3"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(samples.length).eq(400); - - for (let sample of samples) { - expect([-3, -1, 1, 3, 5].includes(sample)).eq(true); - } - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(1, 0.5); - expect(varX).closeTo(((5 ** 2 - 1) * 2 ** 2) / 12, 1); - - let firstSample = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSample.stateValues.mean).closeTo(1, 1e-10); - expect(firstSample.stateValues.variance).closeTo( - ((5 ** 2 - 1) * 2 ** 2) / 12, - 1e-10, - ); - expect(firstSample.stateValues.standardDeviation).closeTo( - Math.sqrt(((5 ** 2 - 1) * 2 ** 2) / 12), - 1e-10, - ); - - let copiedSamples = stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("sample single discrete uniform, no parameters except exclude, get first two non-negative integers", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1 -

- - $p2{name="p3"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(samples.length).eq(400); - - for (let sample of samples) { - expect([1, 3].includes(sample)).eq(true); - } - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(2, 0.2); - expect(varX).closeTo(((2 ** 2 - 1) * 2 ** 2) / 12, 0.2); - - let firstSample = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSample.stateValues.mean).closeTo(2, 1e-10); - expect(firstSample.stateValues.variance).closeTo( - ((2 ** 2 - 1) * 2 ** 2) / 12, - 1e-10, - ); - expect(firstSample.stateValues.standardDeviation).closeTo( - Math.sqrt(((2 ** 2 - 1) * 2 ** 2) / 12), - 1e-10, - ); - - let copiedSamples = stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("sample single discrete uniform, from 0.5 to 4.5, exclude 1.5, 3.5, only to and exclude specified", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1 -

- - $p2{name="p3"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(samples.length).eq(400); - - for (let sample of samples) { - expect([0.5, 2.5, 4.5].includes(sample)).eq(true); - } - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(2.5, 0.3); - expect(varX).closeTo(((3 ** 2 - 1) * 2 ** 2) / 12, 0.5); - - let firstSample = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSample.stateValues.mean).closeTo(2.5, 1e-10); - expect(firstSample.stateValues.variance).closeTo( - ((3 ** 2 - 1) * 2 ** 2) / 12, - 1e-10, - ); - expect(firstSample.stateValues.standardDeviation).closeTo( - Math.sqrt(((3 ** 2 - 1) * 2 ** 2) / 12), - 1e-10, - ); - - let copiedSamples = stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("sample single discrete uniform, from 6.5 to 9.5 exclude 6.5, 8.6, only from and exclude specified", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1 -

- - $p2{name="p3"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(samples.length).eq(400); - - for (let sample of samples) { - expect([7.5, 9.5].includes(sample)).eq(true); - } - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(8.5, 0.2); - expect(varX).closeTo(((2 ** 2 - 1) * 2 ** 2) / 12, 0.05); - - let firstSample = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSample.stateValues.mean).closeTo(8.5, 1e-10); - expect(firstSample.stateValues.variance).closeTo( - ((2 ** 2 - 1) * 2 ** 2) / 12, - 1e-10, - ); - expect(firstSample.stateValues.standardDeviation).closeTo( - Math.sqrt(((2 ** 2 - 1) * 2 ** 2) / 12), - 1e-10, - ); - - let copiedSamples = stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("sample five integers from -3 to 5, excluding -2 and 0", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1 -

- - $p2{name="p3"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(samples.length).eq(400); - - for (let sample of samples) { - expect([-3, -1, 1, 2, 3, 4, 5].includes(sample)).eq(true); - } - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - let firstSample = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - - expect(meanX).closeTo(firstSample.stateValues.mean, 0.5); - expect(varX).closeTo(firstSample.stateValues.variance, 1); - - let copiedSamples = stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("sample 10 odd integers from -3 to 5, excluding 3", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1 -

- - $p2{name="p3"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(samples.length).eq(400); - - for (let sample of samples) { - expect([-3, -1, 1, 5].includes(sample)).eq(true); - } - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - let firstSample = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - - expect(meanX).closeTo(firstSample.stateValues.mean, 0.5); - expect(varX).closeTo(firstSample.stateValues.variance, 1); - - let copiedSamples = stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("sampled number does change dynamically", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

- -

- - - -

- -

-

- $numSamples2{name="numSamples2a"} - $standardDeviation{name="standardDeviationa"} -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let sample1numbers, sample2numbers; - let sample1numbersb, sample2numbersb; - let sample1numbersc, sample2numbersc; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - sample1numbers = stateVariables["/sample1"].replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - sample2numbers = stateVariables["/sample2"].replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(sample1numbers.length).eq(50); - expect(sample2numbers.length).eq(180); - - for (let num of sample1numbers) { - expect(num).gte(0); - expect(num).lt(10); - } - - expect(me.math.mean(sample1numbers)).closeTo(5, 2); - expect(me.math.variance(sample1numbers, "uncorrected")).closeTo( - 10 ** 2 / 12, - 3, - ); - - expect(me.math.mean(sample2numbers)).closeTo(0, 1.5); - expect(me.math.variance(sample2numbers, "uncorrected")).closeTo( - 16, - 8, - ); - }); - - cy.log("Get new samples when change number of samples"); - cy.get(cesc("#\\/numSamples") + " textarea").type( - `{end}{backspace}{backspace}70{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/numSamples2") + " textarea").type( - `{ctrl+home}{shift+end}{backspace}160{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/numSamples2a")).should("contain.text", "160"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - sample1numbersb = stateVariables["/sample1"].replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - sample2numbersb = stateVariables["/sample2"].replacements - .slice( - 0, - stateVariables["/sample2"].replacements.length - - stateVariables["/sample2"].replacementsToWithhold, - ) - .map((x) => stateVariables[x.componentName].stateValues.value); - expect(sample1numbersb.length).eq(70); - expect(sample2numbersb.length).eq(160); - - for (let num of sample1numbersb) { - expect(num).gte(0); - expect(num).lt(10); - } - - expect(me.math.mean(sample1numbersb)).closeTo(5, 2); - expect(me.math.variance(sample1numbersb, "uncorrected")).closeTo( - 10 ** 2 / 12, - 4, - ); - - expect(me.math.mean(sample2numbersb)).closeTo(0, 1); - expect(me.math.variance(sample2numbersb, "uncorrected")).closeTo( - 16, - 6, - ); - - for (let ind = 0; ind < 10; ind++) { - expect(sample1numbersb[ind]).not.eq(sample1numbers[ind]); - } - for (let ind = 0; ind < 10; ind++) { - expect(sample2numbersb[ind]).not.eq(sample2numbers[ind]); - } - }); - - cy.log("Get new samples when sample parameters"); - cy.get(cesc("#\\/maxnum") + " textarea").type( - `{end}{backspace}{backspace}4{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/standardDeviation") + " textarea").type( - `{end}{backspace}{backspace}18{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/standardDeviationa")).should("contain.text", "18"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - sample1numbersc = stateVariables["/sample1"].replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - sample2numbersc = stateVariables["/sample2"].replacements - .slice( - 0, - stateVariables["/sample2"].replacements.length - - stateVariables["/sample2"].replacementsToWithhold, - ) - .map((x) => stateVariables[x.componentName].stateValues.value); - expect(sample1numbersc.length).eq(70); - expect(sample2numbersc.length).eq(160); - - for (let num of sample1numbersc) { - expect(num).gte(0); - expect(num).lt(4); - } - expect(me.math.mean(sample1numbersc)).closeTo(2, 1); - expect(me.math.variance(sample1numbersc, "uncorrected")).closeTo( - 4 ** 2 / 12, - 1, - ); - - expect(me.math.mean(sample2numbersc)).closeTo(0, 6); - expect(me.math.variance(sample2numbersc, "uncorrected")).closeTo( - 18 ** 2, - 120, - ); - - for (let ind = 0; ind < 10; ind++) { - expect(sample1numbersc[ind]).not.eq(sample1numbersb[ind]); - } - for (let ind = 0; ind < 10; ind++) { - expect(sample2numbersc[ind]).not.eq(sample2numbersb[ind]); - } - }); - }); - - it("random number doesn't resample in dynamic map", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - How many numbers do you want? -

- - - - - - -

- -

$_map1

-

$_aslist1

- - $p1{name="p4"} - $p2{name="p5"} - $p3{name="p6"} - - $p4{name="p7"} - $p5{name="p8"} - $p6{name="p9"} -

$_mathinput1{name="m1"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let samplednumbers = []; - - cy.log("initially nothing"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - checkSampledNumbers(stateVariables, []); - }); - - cy.log("sample one number"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}1{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "1"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - samplednumbers.push(n1); - - checkSampledNumbers(stateVariables, samplednumbers); - }); - - cy.log("go back to nothing"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}0{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "0"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - checkSampledNumbers(stateVariables, []); - }); - - cy.log("get same number back"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}1{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "1"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - expect(n1).eq(samplednumbers[0]); - checkSampledNumbers(stateVariables, samplednumbers); - }); - - cy.log("get two more samples"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}3{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "3"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - let n2 = stateVariables["/b/n"].stateValues.value; - let n3 = stateVariables["/c/n"].stateValues.value; - expect(n1).eq(samplednumbers[0]); - samplednumbers.push(n2); - samplednumbers.push(n3); - checkSampledNumbers(stateVariables, samplednumbers); - }); - - cy.log("go back to nothing"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}0{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "0"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - checkSampledNumbers(stateVariables, []); - }); - - cy.log("get first two numbers back"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}2{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "2"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - let n2 = stateVariables["/b/n"].stateValues.value; - expect(n1).eq(samplednumbers[0]); - expect(n2).eq(samplednumbers[1]); - checkSampledNumbers(stateVariables, samplednumbers.slice(0, 2)); - }); - - cy.log("get six total samples"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}6{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "6"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - let n2 = stateVariables["/b/n"].stateValues.value; - let n3 = stateVariables["/c/n"].stateValues.value; - let n4 = stateVariables["/d/n"].stateValues.value; - let n5 = stateVariables["/e/n"].stateValues.value; - let n6 = stateVariables["/f/n"].stateValues.value; - expect(n1).eq(samplednumbers[0]); - expect(n2).eq(samplednumbers[1]); - expect(n3).eq(samplednumbers[2]); - samplednumbers.push(n4); - samplednumbers.push(n5); - samplednumbers.push(n6); - checkSampledNumbers(stateVariables, samplednumbers); - }); - - cy.log("go back to nothing"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}0{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "0"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - checkSampledNumbers(stateVariables, []); - }); - - cy.log("get all six back"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}6{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "6"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - let n2 = stateVariables["/b/n"].stateValues.value; - let n3 = stateVariables["/c/n"].stateValues.value; - let n4 = stateVariables["/d/n"].stateValues.value; - let n5 = stateVariables["/e/n"].stateValues.value; - let n6 = stateVariables["/f/n"].stateValues.value; - expect(n1).eq(samplednumbers[0]); - expect(n2).eq(samplednumbers[1]); - expect(n3).eq(samplednumbers[2]); - expect(n4).eq(samplednumbers[3]); - expect(n5).eq(samplednumbers[4]); - expect(n6).eq(samplednumbers[5]); - checkSampledNumbers(stateVariables, samplednumbers); - }); - }); - - it("sample single discrete uniform number, assign name", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

-

$u{name="u2"}

-

$v{name="v2"}

-

$w{name="w2"}

- `, - }, - "*", - ); - }); - - let options = [3, 10]; - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let u = stateVariables["/u"]; - let u2 = stateVariables["/u2"]; - - expect(options.includes(u.stateValues.value)).eq(true); - expect(u.stateValues.value).eq(u2.stateValues.value); - - let v = stateVariables["/v"]; - let v2 = stateVariables["/v2"]; - expect(options.includes(v.stateValues.value)).eq(true); - expect(v.stateValues.value).eq(v2.stateValues.value); - - let w = stateVariables["/w"]; - let w2 = stateVariables["/w2"]; - expect(options.includes(w.stateValues.value)).eq(true); - expect(w.stateValues.value).eq(w2.stateValues.value); - }); - }); - - it("sample multiple uniform random numbers, assign names", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- -

-

$u{name="u2"}

-

$v{name="v2"}

-

$w{name="w2"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let results = []; - - for (let ind = 0; ind < 6; ind++) { - cy.get(cesc("#\\/_p1") + " > :nth-child(" + (2 * ind + 4) + ")") - .invoke("text") - .then((text) => { - let num = Number(text); - results[ind] = num; - expect(num).gte(3); - expect(num).lt(13); - }); - } - - cy.log("check by name").then(() => { - cy.get(cesc("#\\/u")).should("have.text", results[0]); - cy.get(cesc("#\\/u2")).should("have.text", results[0]); - cy.get(cesc("#\\/v")).should("have.text", results[1]); - cy.get(cesc("#\\/v2")).should("have.text", results[1]); - cy.get(cesc("#\\/w")).should("have.text", results[2]); - cy.get(cesc("#\\/w2")).should("have.text", results[2]); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let u = stateVariables["/u"]; - let u2 = stateVariables["/u2"]; - expect(u.stateValues.value).closeTo(results[0], 1e-8); - expect(u2.stateValues.value).closeTo(results[0], 1e-8); - - let v = stateVariables["/v"]; - let v2 = stateVariables["/v2"]; - expect(v.stateValues.value).closeTo(results[1], 1e-8); - expect(v2.stateValues.value).closeTo(results[1], 1e-8); - - let w = stateVariables["/w"]; - let w2 = stateVariables["/w2"]; - expect(w.stateValues.value).closeTo(results[2], 1e-8); - expect(w2.stateValues.value).closeTo(results[2], 1e-8); - - let s = stateVariables["/s"]; - expect(s.replacements.length).eq(6); - for (let ind = 0; ind < 6; ind++) { - let r = stateVariables[s.replacements[ind].componentName]; - expect(r.stateValues.value).closeTo(results[ind], 1e-8); - } - }); - }); - - it("sample multiple uniform random numbers, assign names, newNamespace", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- -

-

$(s/u{name="u2"})

-

$(s/v{name="v2"})

-

$(s/w{name="w2"})

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let results = []; - - for (let ind = 0; ind < 6; ind++) { - cy.get(cesc("#\\/_p1") + " > :nth-child(" + (2 * ind + 4) + ")") - .invoke("text") - .then((text) => { - let num = Number(text); - results[ind] = num; - expect(num).gte(3); - expect(num).lt(13); - }); - } - - cy.log("check by name").then(() => { - cy.get(cesc("#\\/s\\/u")).should("have.text", results[0]); - cy.get(cesc("#\\/u2")).should("have.text", results[0]); - cy.get(cesc("#\\/s\\/v")).should("have.text", results[1]); - cy.get(cesc("#\\/v2")).should("have.text", results[1]); - cy.get(cesc("#\\/s\\/w")).should("have.text", results[2]); - cy.get(cesc("#\\/w2")).should("have.text", results[2]); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let u = stateVariables["/s/u"]; - let u2 = stateVariables["/u2"]; - expect(u.stateValues.value).closeTo(results[0], 1e-8); - expect(u2.stateValues.value).closeTo(results[0], 1e-8); - - let v = stateVariables["/s/v"]; - let v2 = stateVariables["/v2"]; - expect(v.stateValues.value).closeTo(results[1], 1e-8); - expect(v2.stateValues.value).closeTo(results[1], 1e-8); - - let w = stateVariables["/s/w"]; - let w2 = stateVariables["/w2"]; - expect(w.stateValues.value).closeTo(results[2], 1e-8); - expect(w2.stateValues.value).closeTo(results[2], 1e-8); - - let s = stateVariables["/s"]; - expect(s.replacements.length).eq(6); - for (let ind = 0; ind < 6; ind++) { - let r = stateVariables[s.replacements[ind].componentName]; - expect(r.stateValues.value).closeTo(results[ind], 1e-8); - } - }); - }); - - it("asList", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let results = []; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - results.push(stateVariables["/u"].stateValues.value); - results.push(stateVariables["/v"].stateValues.value); - results.push(stateVariables["/w"].stateValues.value); - results.push(stateVariables["/x"].stateValues.value); - results.push(stateVariables["/y"].stateValues.value); - - for (let num of results) { - expect(num).gte(175).lte(205); - } - - let roundedResults = results.map((x) => Math.round(x * 100) / 100); - cy.get(cesc2("#/_p1")).should( - "have.text", - roundedResults.join(", "), - ); - cy.get(cesc2("#/_p2")).should("have.text", roundedResults.join("")); - }); - }); - - it("copying parameters", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Number of samples

-

Specified type of random number

-

Specified mean

-

Specified variance

-

Specified from

-

Specified to

-

Specified step

-

Actual type: $samples.type{obtainPropFromComposite assignNames="actualType"}

-

Actual from: $samples.from{obtainPropFromComposite assignNames="actualFrom"}

-

Actual to: $samples.to{obtainPropFromComposite assignNames="actualTo"}

-

Actual step: $samples.step{obtainPropFromComposite assignNames="actualStep"}

-

Expected mean: $samples.mean{obtainPropFromComposite assignNames="expectedMean" displayDigits="10"}

-

Expected variance: $samples.variance{obtainPropFromComposite assignNames="expectedVariance" displayDigits="10"}

-

Expected standard deviation: $samples.standardDeviation{obtainPropFromComposite assignNames="expectedStandardDeviation" displayDigits="10"}

-

Resulting mean: $samples

-

Resulting variance: $samples

-

Resulting standard deviation: $samples

-

- -

-

$samples

-

$_aslist1

- - $p1{name="p4"} - $p2{name="p5"} - $p3{name="p6"} - - $p4{name="p7"} - $p5{name="p8"} - $p6{name="p9"} - -

- $nSamples{name="nSamplesa"} - $specifiedTo{name="specifiedToa"} - $type{name="typea"} - $specifiedVariance{name="specifiedVariancea"} -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let checkSamples = function ({ - numSamples, - specifiedType, - specifiedMean, - specifiedVariance, - specifiedFrom, - specifiedTo, - specifiedStep, - sampleComponent, - allowedErrorInMean, - allowedErrorInVariance, - checkAllSamples = true, - stateVariables, - }) { - let nReplacements = sampleComponent.replacements.length; - if (sampleComponent.replacementsToWithhold) { - nReplacements -= sampleComponent.replacementsToWithhold; - } - let samples = sampleComponent.replacements - .slice(0, nReplacements) - .map((x) => stateVariables[x.componentName].stateValues.value); - expect(samples.length).eq(numSamples); - - cy.get(cesc("#\\/nSamples") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect( - text - .replace(/[\s\u200B-\u200D\uFEFF]/g, "") - .replace(/−/, "-"), - ).equal(numSamples.toString()); - }); - cy.get(cesc("#\\/type_input")).should("have.value", specifiedType); - cy.get(cesc("#\\/specifiedMean") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect( - text - .replace(/[\s\u200B-\u200D\uFEFF]/g, "") - .replace(/−/, "-"), - ).equal(specifiedMean.toString()); - }); - cy.get(cesc("#\\/specifiedVariance") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect( - text - .replace(/[\s\u200B-\u200D\uFEFF]/g, "") - .replace(/−/, "-"), - ).equal(specifiedVariance.toString()); - }); - cy.get(cesc("#\\/specifiedFrom") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect( - text - .replace(/[\s\u200B-\u200D\uFEFF]/g, "") - .replace(/−/, "-"), - ).equal(specifiedFrom.toString()); - }); - cy.get(cesc("#\\/specifiedTo") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect( - text - .replace(/[\s\u200B-\u200D\uFEFF]/g, "") - .replace(/−/, "-"), - ).equal(specifiedTo.toString()); - }); - cy.get(cesc("#\\/specifiedStep") + " .mq-editable-field") - .invoke("text") - .then((text) => { - expect( - text - .replace(/[\s\u200B-\u200D\uFEFF]/g, "") - .replace(/−/, "-"), - ).equal(specifiedStep.toString()); - }); - - let type = specifiedType.toLowerCase(); - if (!["gaussian", "uniform", "discreteuniform"].includes(type)) { - type = "uniform"; - } - - cy.get(cesc("#\\/actualType")).should("have.text", type); - - let from = specifiedFrom; - let to = specifiedTo; - let step = specifiedStep; - let expectedMean = specifiedMean; - let expectedVariance = specifiedVariance; - - if (type === "uniform") { - step = "NaN"; - expectedMean = (to + from) / 2; - expectedVariance = (to - from) ** 2 / 12; - } else if (type === "discreteuniform") { - to = from + Math.floor((to - from) / step) * step; - expectedMean = (to + from) / 2; - expectedVariance = - ((((to - from) / step + 1) ** 2 - 1) * step ** 2) / 12; - } else { - from = "NaN"; - to = "NaN"; - step = "NaN"; - } - - let expectedStandardDeviation = Math.sqrt(expectedVariance); - - cy.get(cesc(`#\\/actualFrom`)).should("have.text", from); - cy.get(cesc(`#\\/actualTo`)).should("have.text", to); - cy.get(cesc(`#\\/actualStep`)).should("have.text", step); - cy.get(cesc(`#\\/expectedMean`)) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(expectedMean, 1e-8); - }); - cy.get(cesc(`#\\/expectedVariance`)) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo(expectedVariance, 1e-8); - }); - cy.get(cesc(`#\\/expectedStandardDeviation`)) - .invoke("text") - .then((text) => { - expect(Number(text)).closeTo( - expectedStandardDeviation, - 1e-8, - ); - }); - - let resultingMean = me.math.mean(samples); - let resultingVariance = me.math.variance(samples); - let resultingStandardDeviation = Math.sqrt(resultingVariance); - - cy.get(cesc(`#\\/resultingMean`) + ` .mjx-mrow`) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo( - resultingMean, - 1e-8, - ); - expect(resultingMean).closeTo( - expectedMean, - allowedErrorInMean, - ); - }); - cy.get(cesc(`#\\/resultingVariance`) + ` .mjx-mrow`) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo( - resultingVariance, - 1e-8, - ); - expect(resultingVariance).closeTo( - expectedVariance, - allowedErrorInVariance, - ); - }); - cy.get(cesc(`#\\/resultingStandardDeviation`) + ` .mjx-mrow`) - .invoke("text") - .then((text) => { - expect(Number(text.replace(/−/, "-"))).closeTo( - resultingStandardDeviation, - 1e-8, - ); - expect(resultingStandardDeviation).closeTo( - expectedStandardDeviation, - Math.sqrt(allowedErrorInVariance), - ); - }); - - if (checkAllSamples) { - for (let ind = 1; ind <= 9; ind++) { - cy.get(cesc(`#\\/p${ind}`)) - .invoke("text") - .then((text) => { - let numbers = text.split(",").map(Number); - expect(numbers.length).eq(numSamples); - for (let [i, num] of numbers.entries()) { - expect(num).closeTo(samples[i], 1e-8); - } - }); - } - } - }; - - let numSamples = 10; - let specifiedType = ""; - let specifiedMean = 0; - let specifiedVariance = 1; - let specifiedFrom = 0; - let specifiedTo = 1; - let specifiedStep = 1; - - cy.log("initial values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - checkSamples({ - numSamples, - specifiedType, - specifiedMean, - specifiedVariance, - specifiedFrom, - specifiedTo, - specifiedStep, - sampleComponent: stateVariables["/samples"], - allowedErrorInMean: 0.4, - allowedErrorInVariance: 0.4, - stateVariables, - }); - }); - - cy.log("Increase number of samples").then(() => { - numSamples = 50; - }); - cy.get(cesc(`#\\/nSamples`) + ` textarea`).type( - "{end}{backspace}{backspace}50{enter}", - { force: true }, - ); - cy.get(cesc("#\\/nSamplesa")).should("contain.text", "50"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - checkSamples({ - numSamples, - specifiedType, - specifiedMean, - specifiedVariance, - specifiedFrom, - specifiedTo, - specifiedStep, - sampleComponent: stateVariables["/samples"], - allowedErrorInMean: 0.2, - allowedErrorInVariance: 0.2, - checkAllSamples: false, - stateVariables, - }); - }); - - cy.log("change from and to").then(() => { - specifiedFrom = -3; - specifiedTo = 0; - }); - cy.get(cesc(`#\\/specifiedFrom`) + ` textarea`).type( - "{end}{backspace}{backspace}-3{enter}", - { force: true }, - ); - cy.get(cesc(`#\\/specifiedTo`) + ` textarea`).type( - "{end}{backspace}{backspace}0{enter}", - { force: true }, - ); - cy.get(cesc("#\\/specifiedToa")).should("contain.text", "0"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - checkSamples({ - numSamples, - specifiedType, - specifiedMean, - specifiedVariance, - specifiedFrom, - specifiedTo, - specifiedStep, - sampleComponent: stateVariables["/samples"], - allowedErrorInMean: 0.4, - allowedErrorInVariance: 0.4, - checkAllSamples: false, - stateVariables, - }); - }); - - cy.log("change type to discrete uniform").then(() => { - specifiedType = "discreteUniform"; - }); - cy.get(cesc(`#\\/type_input`)).clear().type("discreteUniform{enter}"); - cy.get(cesc("#\\/typea")).should("contain.text", "discreteUniform"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - checkSamples({ - numSamples, - specifiedType, - specifiedMean, - specifiedVariance, - specifiedFrom, - specifiedTo, - specifiedStep, - sampleComponent: stateVariables["/samples"], - allowedErrorInMean: 0.4, - allowedErrorInVariance: 0.4, - checkAllSamples: false, - stateVariables, - }); - }); - - cy.log("change from, to, and step").then(() => { - specifiedFrom = 3; - specifiedTo = -8; - specifiedStep = -4; - }); - cy.get(cesc(`#\\/specifiedFrom`) + ` textarea`).type( - "{end}{backspace}{backspace}3{enter}", - { force: true }, - ); - cy.get(cesc(`#\\/specifiedStep`) + ` textarea`).type( - "{end}{backspace}{backspace}-4{enter}", - { force: true }, - ); - cy.get(cesc(`#\\/specifiedTo`) + ` textarea`).type( - "{end}{backspace}{backspace}-8{enter}", - { force: true }, - ); - cy.get(cesc("#\\/specifiedToa")).should("contain.text", "−8"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - checkSamples({ - numSamples, - specifiedType, - specifiedMean, - specifiedVariance, - specifiedFrom, - specifiedTo, - specifiedStep, - sampleComponent: stateVariables["/samples"], - allowedErrorInMean: 1.5, - allowedErrorInVariance: 3, - checkAllSamples: false, - stateVariables, - }); - }); - - cy.log("change type to gaussian").then(() => { - specifiedType = "gaussian"; - }); - cy.get(cesc(`#\\/type_input`)).clear().type("gaussian{enter}"); - cy.get(cesc("#\\/typea")).should("contain.text", "gaussian"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - checkSamples({ - numSamples, - specifiedType, - specifiedMean, - specifiedVariance, - specifiedFrom, - specifiedTo, - specifiedStep, - sampleComponent: stateVariables["/samples"], - allowedErrorInMean: 0.8, - allowedErrorInVariance: 0.8, - checkAllSamples: false, - stateVariables, - }); - }); - - cy.log("change mean and variance").then(() => { - specifiedMean = -11; - specifiedVariance = 3; - }); - cy.get(cesc(`#\\/specifiedMean`) + ` textarea`).type( - "{end}{backspace}{backspace}-11{enter}", - { force: true }, - ); - cy.get(cesc(`#\\/specifiedVariance`) + ` textarea`).type( - "{end}{backspace}{backspace}3{enter}", - { force: true }, - ); - cy.get(cesc(`#\\/specifiedVariancea`)).should("contain.text", "3"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - checkSamples({ - numSamples, - specifiedType, - specifiedMean, - specifiedVariance, - specifiedFrom, - specifiedTo, - specifiedStep, - sampleComponent: stateVariables["/samples"], - allowedErrorInMean: 0.8, - allowedErrorInVariance: 3, - checkAllSamples: false, - stateVariables, - }); - }); - - cy.log("Increase number of samples").then(() => { - numSamples = 200; - }); - cy.get(cesc(`#\\/nSamples`) + ` textarea`).type( - "{end}{backspace}{backspace}200{enter}", - { force: true }, - ); - cy.get(cesc("#\\/nSamplesa")).should("contain.text", "200"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - checkSamples({ - numSamples, - specifiedType, - specifiedMean, - specifiedVariance, - specifiedFrom, - specifiedTo, - specifiedStep, - sampleComponent: stateVariables["/samples"], - allowedErrorInMean: 0.4, - allowedErrorInVariance: 0.8, - checkAllSamples: false, - stateVariables, - }); - }); - - cy.log("Decrease number of samples").then(() => { - numSamples = 20; - }); - cy.get(cesc(`#\\/nSamples`) + ` textarea`).type( - "{end}{backspace}{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/nSamplesa")).should("not.contain.text", "200"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - checkSamples({ - numSamples, - specifiedType, - specifiedMean, - specifiedVariance, - specifiedFrom, - specifiedTo, - specifiedStep, - sampleComponent: stateVariables["/samples"], - allowedErrorInMean: 1, - allowedErrorInVariance: 3, - checkAllSamples: true, - stateVariables, - }); - }); - }); - it(`different numbers when reload page if don't save state`, () => { let doenetML = ` a @@ -2812,387 +181,4 @@ describe("SampleRandomNumbers Tag Tests", function () { expect(samples2).eqls(samples); }); }); - - it("same numbers for given variant if variantDeterminesSeed", () => { - let doenetML = ` - a -

- - - - -

- - `; - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: 1, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let samples = []; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - samples = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].replacements[0].componentName - ].stateValues.value, - ); - - expect(samples.length).eq(100); - - for (let sample of samples) { - expect(sample).gt(0); - expect(sample).lte(1); - } - }); - - cy.reload(); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: 1, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples2 = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].replacements[0].componentName - ].stateValues.value, - ); - - expect(samples2).eqls(samples); - }); - - cy.reload(); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - requestedVariantIndex: 2, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples2 = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].replacements[0].componentName - ].stateValues.value, - ); - - expect(samples2.length).eq(100); - - for (let [ind, sample] of samples2.entries()) { - expect(sample).gt(0); - expect(sample).lte(1); - expect(sample).not.eq(samples[ind]); - } - }); - }); - - it("rounding", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

-

- -

$n1

-

$n2

-

$n3

-

$n4

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let n1 = stateVariables["/n1"].stateValues.value; - let n2 = stateVariables["/n2"].stateValues.value; - let n3 = stateVariables["/n3"].stateValues.value; - let n4 = stateVariables["/n4"].stateValues.value; - - cy.get(cesc("#\\/n1")).should( - "have.text", - String(Math.round(n1 * 10 ** 8) / 10 ** 8), - ); - cy.get(cesc("#\\/n2")).should( - "have.text", - String(Math.round(n2 * 10 ** 1) / 10 ** 1), - ); - cy.get(cesc("#\\/n3")).should( - "have.text", - String(Math.round(n3 * 10 ** 3) / 10 ** 3), - ); - cy.get(cesc("#\\/n4")).should("have.text", String(n4) + ".0"); - - cy.get(cesc("#\\/n1a")).should( - "have.text", - String(Math.round(n1 * 10 ** 8) / 10 ** 8), - ); - cy.get(cesc("#\\/n2a")).should( - "have.text", - String(Math.round(n2 * 10 ** 1) / 10 ** 1), - ); - cy.get(cesc("#\\/n3a")).should( - "have.text", - String(Math.round(n3 * 10 ** 3) / 10 ** 3), - ); - cy.get(cesc("#\\/n4a")).should("have.text", String(n4) + ".0"); - }); - }); - - it(`resample random numbers`, () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

, - -

- -

- - -

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let rn1, rn2, rn3; - let rn1b, rn2b, rn3b; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - rn1 = stateVariables["/rn1"].stateValues.value; - rn2 = stateVariables["/rn2"].stateValues.value; - rn3 = stateVariables["/rn3"].stateValues.value; - - expect(rn1).gt(1).lt(10); - expect(rn2).gt(1).lt(10); - expect(rn3).gt(1000).lt(10000); - - let rn1Rounded = Math.round(rn1 * 100) / 100; - - cy.get(cesc2("#/rn1")).should("have.text", rn1Rounded.toString()); - - cy.get(cesc2("#/resamp1")).click(); - - cy.get(cesc2("#/rn1")).should( - "not.have.text", - rn1Rounded.toString(), - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - rn1b = stateVariables["/rn1"].stateValues.value; - rn2b = stateVariables["/rn2"].stateValues.value; - rn3b = stateVariables["/rn3"].stateValues.value; - - expect(rn1b).gt(1).lt(10); - expect(rn2b).gt(1).lt(10); - expect(rn3b).gt(1000).lt(10000); - - expect(rn1b).not.eq(rn1); - expect(rn2b).not.eq(rn2); - expect(rn3b).eq(rn3); - - let rn3Rounded = Math.round(rn3 * 100) / 100; - - cy.get(cesc2("#/rn3")).should("have.text", rn3Rounded.toString()); - - cy.get(cesc2("#/resamp2")).click(); - - cy.get(cesc2("#/rn3")).should( - "not.have.text", - rn3Rounded.toString(), - ); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let rn1c = stateVariables["/rn1"].stateValues.value; - let rn2c = stateVariables["/rn2"].stateValues.value; - let rn3c = stateVariables["/rn3"].stateValues.value; - - expect(rn1c).gt(1).lt(10); - expect(rn2c).gt(1).lt(10); - expect(rn3c).gt(1000).lt(10000); - - expect(rn1c).eq(rn1b); - expect(rn2c).eq(rn2b); - expect(rn3c).not.eq(rn3); - }); - }); - - function checkSampledNumbers(stateVariables, samplednumbers) { - let n = samplednumbers.length; - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(n); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(n); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(n); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(n); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(n); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(n); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(n); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(n); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(n); - for (let ind = 0; ind < n; ind++) { - expect( - stateVariables[ - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - } - } }); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/select.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/select.cy.js index 795e9ef27..b566769ee 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/select.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/select.cy.js @@ -1,5 +1,4 @@ -import me from "math-expressions"; -import { cesc, cesc2 } from "@doenet/utils"; +import { cesc2 } from "@doenet/utils"; describe("Select Tag Tests", function () { beforeEach(() => { @@ -7,476 +6,6 @@ describe("Select Tag Tests", function () { cy.visit("/"); }); - it("no parameters, select doesn't do anything", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 10; ind++) { - let x = stateVariables["/x" + ind].stateValues.value; - expect(["u", "v", "w", "x", "y", "z"].includes(x)).eq(true); - } - }); - }); - - it("select multiple maths", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 5; ind++) { - let x = stateVariables["/x" + ind].stateValues.value; - let y = stateVariables["/y" + ind].stateValues.value; - let z = stateVariables["/z" + ind].stateValues.value; - - expect(["u", "v", "w", "x", "y", "z"].includes(x)).eq(true); - expect(["u", "v", "w", "x", "y", "z"].includes(y)).eq(true); - expect(["u", "v", "w", "x", "y", "z"].includes(z)).eq(true); - expect(x).not.eq(y); - expect(x).not.eq(z); - expect(y).not.eq(z); - } - }); - }); - - it("select multiple maths, initially unresolved", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - $n3{name="n2"} - $num1{name="n"} - $n2+$num2 - $n3+$num3 - $num3{name="n3"} - 1 - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - cy.get(cesc("#\\/num1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 5; ind++) { - let x = stateVariables["/x" + ind].stateValues.value; - let y = stateVariables["/y" + ind].stateValues.value; - let z = stateVariables["/z" + ind].stateValues.value; - - expect(["u", "v", "w", "x", "y", "z"].includes(x)).eq(true); - expect(["u", "v", "w", "x", "y", "z"].includes(y)).eq(true); - expect(["u", "v", "w", "x", "y", "z"].includes(z)).eq(true); - expect(x).not.eq(y); - expect(x).not.eq(z); - expect(y).not.eq(z); - } - }); - }); - - it("select multiple maths with namespace", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 5; ind++) { - let x = - stateVariables["/s" + ind + "/x" + ind].stateValues.value; - let y = - stateVariables["/s" + ind + "/y" + ind].stateValues.value; - let z = - stateVariables["/s" + ind + "/z" + ind].stateValues.value; - - expect(["u", "v", "w", "x", "y", "z"].includes(x)).eq(true); - expect(["u", "v", "w", "x", "y", "z"].includes(y)).eq(true); - expect(["u", "v", "w", "x", "y", "z"].includes(z)).eq(true); - expect(x).not.eq(y); - expect(x).not.eq(z); - expect(y).not.eq(z); - } - }); - }); - - it("select multiple maths, with replacement", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 5; ind++) { - let x = stateVariables["/x" + ind].stateValues.value; - let y = stateVariables["/y" + ind].stateValues.value; - let z = stateVariables["/z" + ind].stateValues.value; - - expect(["x", "y", "z"].includes(x)).eq(true); - expect(["x", "y", "z"].includes(y)).eq(true); - expect(["x", "y", "z"].includes(z)).eq(true); - - let s = stateVariables["/s" + ind]; - - for (let i = 3; i < 5; i++) { - expect( - ["x", "y", "z"].includes( - stateVariables[ - stateVariables[s.replacements[i].componentName] - .replacements[0].componentName - ].stateValues.value, - ), - ).eq(true); - } - } - }); - }); - - it("asList", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

- - - - - - - - - -

- -

- - $s1{name="noresample1"} - $s2{name="noresample2"} - $noresample1{name="noreresample1"} - $noresample2{name="noreresample2"} - -

- -

- $_aslist1{name="noresamplelist"} -

- -

- $noresamplelist{name="noreresamplelist"} -

- - $_p1{name="noresamplep"} - $noresamplep{name="noreresamplep"} - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let x1 = - stateVariables[ - stateVariables[ - stateVariables["/s1"].replacements[0].componentName - ].replacements[0].componentName - ].stateValues.value; - let x2 = - stateVariables[ - stateVariables[ - stateVariables["/s2"].replacements[0].componentName - ].replacements[0].componentName - ].stateValues.value; - expect(["u", "v", "w", "x", "y", "z"].includes(x1)).eq(true); - expect(["u", "v", "w", "x", "y", "z"].includes(x2)).eq(true); - - expect( - stateVariables[ - stateVariables[ - stateVariables["/noresample1"].replacements[0] - .componentName - ].replacements[0].componentName - ].stateValues.value, - ).eq(x1); - expect( - stateVariables[ - stateVariables[ - stateVariables["/noresample2"].replacements[0] - .componentName - ].replacements[0].componentName - ].stateValues.value, - ).eq(x2); - expect( - stateVariables[ - stateVariables[ - stateVariables["/noreresample1"].replacements[0] - .componentName - ].replacements[0].componentName - ].stateValues.value, - ).eq(x1); - expect( - stateVariables[ - stateVariables[ - stateVariables["/noreresample2"].replacements[0] - .componentName - ].replacements[0].componentName - ].stateValues.value, - ).eq(x2); - - expect( - stateVariables[ - stateVariables["/noresamplelist"].activeChildren[0] - .componentName - ].stateValues.value, - ).eq(x1); - expect( - stateVariables[ - stateVariables["/noresamplelist"].activeChildren[1] - .componentName - ].stateValues.value, - ).eq(x2); - expect( - stateVariables[ - stateVariables["/noreresamplelist"].activeChildren[0] - .componentName - ].stateValues.value, - ).eq(x1); - expect( - stateVariables[ - stateVariables["/noreresamplelist"].activeChildren[1] - .componentName - ].stateValues.value, - ).eq(x2); - - expect( - stateVariables[ - stateVariables[ - stateVariables["/noresamplep"].activeChildren[1] - .componentName - ].activeChildren[0].componentName - ].stateValues.value, - ).eq(x1); - expect( - stateVariables[ - stateVariables[ - stateVariables["/noresamplep"].activeChildren[1] - .componentName - ].activeChildren[1].componentName - ].stateValues.value, - ).eq(x2); - expect( - stateVariables[ - stateVariables[ - stateVariables["/noreresamplep"].activeChildren[1] - .componentName - ].activeChildren[0].componentName - ].stateValues.value, - ).eq(x1); - expect( - stateVariables[ - stateVariables[ - stateVariables["/noreresamplep"].activeChildren[1] - .componentName - ].activeChildren[1].componentName - ].stateValues.value, - ).eq(x2); - }); - }); - - it("select doesn't change dynamically", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Number to select:

-

First option:

-

Second option:

-

Third option:

-

- Selected choices: - - -

- -

Selected choices: - - - - -

-

-

-

$x1$y1$z1

-

$x2$y2$z2

-

$x3$y3$z3

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - let lists = { - x: ["x", "y", "z"], - u: ["u", "v", "w"], - a: ["a", "b", "c"], - q: ["q", "r", "s"], - }; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let x1 = stateVariables["/x1"].stateValues.value; - let y1 = stateVariables["/y1"].stateValues.value; - let z1 = stateVariables["/z1"].stateValues.value; - let x2 = stateVariables["/x2"].stateValues.value; - let y2 = stateVariables["/y2"].stateValues.value; - let z2 = stateVariables["/z2"].stateValues.value; - let x3 = stateVariables["/x3"].stateValues.value; - let y3 = stateVariables["/y3"].stateValues.value; - let z3 = stateVariables["/z3"].stateValues.value; - - let list1 = lists[x1]; - let list2 = lists[x2]; - let list3 = lists[x3]; - - expect(y1).eq(list1[1]); - expect(z1).eq(list1[2]); - expect(y2).eq(list2[1]); - expect(z2).eq(list2[2]); - expect(y3).eq(list3[1]); - expect(z3).eq(list3[2]); - - for (let name of ["/p1", "/q1"]) { - let aslistChildren = stateVariables[ - stateVariables[name].activeChildren[0].componentName - ].activeChildren.map((x) => stateVariables[x.componentName]); - for (let ind = 0; ind < 3; ind++) { - expect(aslistChildren[ind].stateValues.value).eq( - list1[ind], - ); - } - } - for (let name of ["/p2", "/q2"]) { - let aslistChildren = stateVariables[ - stateVariables[name].activeChildren[0].componentName - ].activeChildren.map((x) => stateVariables[x.componentName]); - for (let ind = 0; ind < 3; ind++) { - expect(aslistChildren[ind].stateValues.value).eq( - list2[ind], - ); - } - } - for (let name of ["/p3", "/q3"]) { - let aslistChildren = stateVariables[ - stateVariables[name].activeChildren[0].componentName - ].activeChildren.map((x) => stateVariables[x.componentName]); - for (let ind = 0; ind < 3; ind++) { - expect(aslistChildren[ind].stateValues.value).eq( - list3[ind], - ); - } - } - }); - }); - - it("select single group of maths, assign names with namespace to grandchildren", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 -

-

-

-

$(s1/x)$(s1/y)$(s1/z)

-

$(s2/x)$(s2/y)$(s2/z)

-

$(s3/x)$(s3/y)$(s3/z)

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - let lists = { - x: ["x", "y", "z"], - u: ["u", "v", "w"], - a: ["a", "b", "c"], - q: ["q", "r", "s"], - }; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let x1 = stateVariables["/s1/x"].stateValues.value; - let y1 = stateVariables["/s1/y"].stateValues.value; - let z1 = stateVariables["/s1/z"].stateValues.value; - let x2 = stateVariables["/s2/x"].stateValues.value; - let y2 = stateVariables["/s2/y"].stateValues.value; - let z2 = stateVariables["/s2/z"].stateValues.value; - let x3 = stateVariables["/s3/x"].stateValues.value; - let y3 = stateVariables["/s3/y"].stateValues.value; - let z3 = stateVariables["/s3/z"].stateValues.value; - - let list1 = lists[x1]; - let list2 = lists[x2]; - let list3 = lists[x3]; - - expect(y1).eq(list1[1]); - expect(z1).eq(list1[2]); - expect(y2).eq(list2[1]); - expect(z2).eq(list2[2]); - expect(y3).eq(list3[1]); - expect(z3).eq(list3[2]); - - for (let name of ["/p1", "/q1"]) { - let aslistChildren = stateVariables[ - stateVariables[name].activeChildren[0].componentName - ].activeChildren.map((x) => stateVariables[x.componentName]); - for (let ind = 0; ind < 3; ind++) { - expect(aslistChildren[ind].stateValues.value).eq( - list1[ind], - ); - } - } - for (let name of ["/p2", "/q2"]) { - let aslistChildren = stateVariables[ - stateVariables[name].activeChildren[0].componentName - ].activeChildren.map((x) => stateVariables[x.componentName]); - for (let ind = 0; ind < 3; ind++) { - expect(aslistChildren[ind].stateValues.value).eq( - list2[ind], - ); - } - } - for (let name of ["/p3", "/q3"]) { - let aslistChildren = stateVariables[ - stateVariables[name].activeChildren[0].componentName - ].activeChildren.map((x) => stateVariables[x.componentName]); - for (let ind = 0; ind < 3; ind++) { - expect(aslistChildren[ind].stateValues.value).eq( - list3[ind], - ); - } - } - }); - }); - - it("select multiple group of maths, assign names to grandchildren", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 -

- -

-

- $x1$y1$z1 - $x2$y2$z2 - $x3$y3$z3 -

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - let lists = { - x: ["x", "y", "z"], - u: ["u", "v", "w"], - a: ["a", "b", "c"], - q: ["q", "r", "s"], - }; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let x1 = stateVariables["/x1"].stateValues.value; - let y1 = stateVariables["/y1"].stateValues.value; - let z1 = stateVariables["/z1"].stateValues.value; - let x2 = stateVariables["/x2"].stateValues.value; - let y2 = stateVariables["/y2"].stateValues.value; - let z2 = stateVariables["/z2"].stateValues.value; - let x3 = stateVariables["/x3"].stateValues.value; - let y3 = stateVariables["/y3"].stateValues.value; - let z3 = stateVariables["/z3"].stateValues.value; - - let list1 = lists[x1]; - let list2 = lists[x2]; - let list3 = lists[x3]; - - let listsByInd = [list1, list2, list3]; - - expect(x1).not.eq(x2); - expect(x1).not.eq(x3); - expect(x2).not.eq(x3); - - expect(y1).eq(list1[1]); - expect(z1).eq(list1[2]); - expect(y2).eq(list2[1]); - expect(z2).eq(list2[2]); - expect(y3).eq(list3[1]); - expect(z3).eq(list3[2]); - - for (let name of ["/p1", "/q1"]) { - let aslistChildren = stateVariables[ - stateVariables[name].activeChildren[0].componentName - ].activeChildren.map((x) => stateVariables[x.componentName]); - for (let ind1 = 0; ind1 < 3; ind1++) { - for (let ind2 = 0; ind2 < 3; ind2++) { - expect( - aslistChildren[ind1 * 3 + ind2].stateValues.value, - ).eq(listsByInd[ind1][ind2]); - } - } - } - }); - }); - - it("references to outside components", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 - x - y - z - - - - a - b - c - -

Selected options repeated

- $q{name="q2"} - $r{name="r2"} - $s{name="s2"} - $t{name="t2"} - $u{name="u2"} - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - let option = { - "Option 1: ": me.fromText("3xa"), - "Option 2: ": me.fromText("4yb"), - "Option 3: ": me.fromText("5zc"), - }; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let q2 = - stateVariables[ - stateVariables["/q2"].replacements[0].componentName - ].activeChildren; - let q2string = q2[0]; - let q2math = me.fromAst( - stateVariables[q2[1].componentName].stateValues.value, - ); - expect(q2math.equals(option[q2string])).eq(true); - - let r2 = - stateVariables[ - stateVariables["/r2"].replacements[0].componentName - ].activeChildren; - let r2string = r2[0]; - let r2math = me.fromAst( - stateVariables[r2[1].componentName].stateValues.value, - ); - expect(r2math.equals(option[r2string])).eq(true); - - let s2 = - stateVariables[ - stateVariables["/s2"].replacements[0].componentName - ].activeChildren; - let s2string = s2[0]; - let s2math = me.fromAst( - stateVariables[s2[1].componentName].stateValues.value, - ); - expect(s2math.equals(option[s2string])).eq(true); - - let t2 = - stateVariables[ - stateVariables["/t2"].replacements[0].componentName - ].activeChildren; - let t2string = t2[0]; - let t2math = me.fromAst( - stateVariables[t2[1].componentName].stateValues.value, - ); - expect(t2math.equals(option[t2string])).eq(true); - - let u2 = - stateVariables[ - stateVariables["/u2"].replacements[0].componentName - ].activeChildren; - let u2string = u2[0]; - let u2math = me.fromAst( - stateVariables[u2[1].componentName].stateValues.value, - ); - expect(u2math.equals(option[u2string])).eq(true); - }); - }); - - it("references to outside components, no new namespace", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 - x - y - z - - - - a - b - c - -

Selected options repeated

- $q{name="q2"} - $r{name="r2"} - $s{name="s2"} - $t{name="t2"} - $u{name="u2"} - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - let option = { - "Option 1: ": me.fromText("3xa"), - "Option 2: ": me.fromText("4yb"), - "Option 3: ": me.fromText("5zc"), - }; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let q2 = - stateVariables[ - stateVariables["/q2"].replacements[0].componentName - ].activeChildren; - let q2string = q2[0]; - let q2math = me.fromAst( - stateVariables[q2[1].componentName].stateValues.value, - ); - expect(q2math.equals(option[q2string])).eq(true); - - let r2 = - stateVariables[ - stateVariables["/r2"].replacements[0].componentName - ].activeChildren; - let r2string = r2[0]; - let r2math = me.fromAst( - stateVariables[r2[1].componentName].stateValues.value, - ); - expect(r2math.equals(option[r2string])).eq(true); - - let s2 = - stateVariables[ - stateVariables["/s2"].replacements[0].componentName - ].activeChildren; - let s2string = s2[0]; - let s2math = me.fromAst( - stateVariables[s2[1].componentName].stateValues.value, - ); - expect(s2math.equals(option[s2string])).eq(true); - - let t2 = - stateVariables[ - stateVariables["/t2"].replacements[0].componentName - ].activeChildren; - let t2string = t2[0]; - let t2math = me.fromAst( - stateVariables[t2[1].componentName].stateValues.value, - ); - expect(t2math.equals(option[t2string])).eq(true); - - let u2 = - stateVariables[ - stateVariables["/u2"].replacements[0].componentName - ].activeChildren; - let u2string = u2[0]; - let u2math = me.fromAst( - stateVariables[u2[1].componentName].stateValues.value, - ); - expect(u2math.equals(option[u2string])).eq(true); - }); - }); - - it("internal references", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - -

Selected options repeated

- $q{name="q2"} - $r{name="r2"} - $s{name="s2"} - $t{name="t2"} - $u{name="u2"} - -

Copy x from within selection options

-

$(q/x{name="qx"})

-

$(r/x{name="rx"})

-

$(s/x{name="sx"})

-

$(t/x{name="tx"})

-

$(u/x{name="ux"})

- -

Copy select itself

-
$_select1
- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let option = { - "Option 1: ": me.fromText("3x+a+x^2a^3"), - "Option 2: ": me.fromText("4y+b+y^2b^3"), - "Option 3: ": me.fromText("5z+c+z^2c^3"), - }; - - let xoption = { - "Option 1: ": "x", - "Option 2: ": "y", - "Option 3: ": "z", - }; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let q2 = - stateVariables[ - stateVariables["/q2"].replacements[0].componentName - ].activeChildren; - let q2string = q2[0]; - let q2math = me.fromAst( - stateVariables[q2[1].componentName].stateValues.value, - ); - expect(q2math.equals(option[q2string])).eq(true); - let qx = stateVariables["/qx"].stateValues.value; - expect(qx).eq(xoption[q2string]); - let repeatqmath = me.fromAst( - stateVariables[ - stateVariables[ - stateVariables["/repeat"].activeChildren[0] - .componentName - ].activeChildren[1].componentName - ].stateValues.value, - ); - expect(repeatqmath.equals(option[q2string])).eq(true); - - let r2 = - stateVariables[ - stateVariables["/r2"].replacements[0].componentName - ].activeChildren; - let r2string = r2[0]; - let r2math = me.fromAst( - stateVariables[r2[1].componentName].stateValues.value, - ); - expect(r2math.equals(option[r2string])).eq(true); - let rx = stateVariables["/rx"].stateValues.value; - expect(rx).eq(xoption[r2string]); - let repeatrmath = me.fromAst( - stateVariables[ - stateVariables[ - stateVariables["/repeat"].activeChildren[1] - .componentName - ].activeChildren[1].componentName - ].stateValues.value, - ); - expect(repeatrmath.equals(option[r2string])).eq(true); - - let s2 = - stateVariables[ - stateVariables["/s2"].replacements[0].componentName - ].activeChildren; - let s2string = s2[0]; - let s2math = me.fromAst( - stateVariables[s2[1].componentName].stateValues.value, - ); - expect(s2math.equals(option[s2string])).eq(true); - let sx = stateVariables["/sx"].stateValues.value; - expect(sx).eq(xoption[s2string]); - let repeatsmath = me.fromAst( - stateVariables[ - stateVariables[ - stateVariables["/repeat"].activeChildren[2] - .componentName - ].activeChildren[1].componentName - ].stateValues.value, - ); - expect(repeatsmath.equals(option[s2string])).eq(true); - - let t2 = - stateVariables[ - stateVariables["/t2"].replacements[0].componentName - ].activeChildren; - let t2string = t2[0]; - let t2math = me.fromAst( - stateVariables[t2[1].componentName].stateValues.value, - ); - expect(t2math.equals(option[t2string])).eq(true); - let tx = stateVariables["/tx"].stateValues.value; - expect(tx).eq(xoption[t2string]); - let repeattmath = me.fromAst( - stateVariables[ - stateVariables[ - stateVariables["/repeat"].activeChildren[3] - .componentName - ].activeChildren[1].componentName - ].stateValues.value, - ); - expect(repeattmath.equals(option[t2string])).eq(true); - - let u2 = - stateVariables[ - stateVariables["/u2"].replacements[0].componentName - ].activeChildren; - let u2string = u2[0]; - let u2math = me.fromAst( - stateVariables[u2[1].componentName].stateValues.value, - ); - expect(u2math.equals(option[u2string])).eq(true); - let ux = stateVariables["/ux"].stateValues.value; - expect(ux).eq(xoption[u2string]); - let repeatumath = me.fromAst( - stateVariables[ - stateVariables[ - stateVariables["/repeat"].activeChildren[4] - .componentName - ].activeChildren[1].componentName - ].stateValues.value, - ); - expect(repeatumath.equals(option[u2string])).eq(true); - }); - }); - - it("internal references with no new namespace", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - -

Selected options repeated

- $q{name="q2"} - $r{name="r2"} - $s{name="s2"} - $t{name="t2"} - $u{name="u2"} - -

Copy select itself

-
$_select1
- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let option = { - "Option 1: ": me.fromText("3x+a+x^2a^3"), - "Option 2: ": me.fromText("4y+b+y^2b^3"), - "Option 3: ": me.fromText("5z+c+z^2c^3"), - }; - - let xoption = { - "Option 1: ": "x", - "Option 2: ": "y", - "Option 3: ": "z", - }; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let q2 = - stateVariables[ - stateVariables["/q2"].replacements[0].componentName - ].activeChildren; - let q2string = q2[0]; - let q2math = me.fromAst( - stateVariables[q2[1].componentName].stateValues.value, - ); - expect(q2math.equals(option[q2string])).eq(true); - let repeatqmath = me.fromAst( - stateVariables[ - stateVariables[ - stateVariables["/repeat"].activeChildren[0] - .componentName - ].activeChildren[1].componentName - ].stateValues.value, - ); - expect(repeatqmath.equals(option[q2string])).eq(true); - - let r2 = - stateVariables[ - stateVariables["/r2"].replacements[0].componentName - ].activeChildren; - let r2string = r2[0]; - let r2math = me.fromAst( - stateVariables[r2[1].componentName].stateValues.value, - ); - expect(r2math.equals(option[r2string])).eq(true); - let repeatrmath = me.fromAst( - stateVariables[ - stateVariables[ - stateVariables["/repeat"].activeChildren[1] - .componentName - ].activeChildren[1].componentName - ].stateValues.value, - ); - expect(repeatrmath.equals(option[r2string])).eq(true); - - let s2 = - stateVariables[ - stateVariables["/s2"].replacements[0].componentName - ].activeChildren; - let s2string = s2[0]; - let s2math = me.fromAst( - stateVariables[s2[1].componentName].stateValues.value, - ); - expect(s2math.equals(option[s2string])).eq(true); - let repeatsmath = me.fromAst( - stateVariables[ - stateVariables[ - stateVariables["/repeat"].activeChildren[2] - .componentName - ].activeChildren[1].componentName - ].stateValues.value, - ); - expect(repeatsmath.equals(option[s2string])).eq(true); - - let t2 = - stateVariables[ - stateVariables["/t2"].replacements[0].componentName - ].activeChildren; - let t2string = t2[0]; - let t2math = me.fromAst( - stateVariables[t2[1].componentName].stateValues.value, - ); - expect(t2math.equals(option[t2string])).eq(true); - let repeattmath = me.fromAst( - stateVariables[ - stateVariables[ - stateVariables["/repeat"].activeChildren[3] - .componentName - ].activeChildren[1].componentName - ].stateValues.value, - ); - expect(repeattmath.equals(option[t2string])).eq(true); - - let u2 = - stateVariables[ - stateVariables["/u2"].replacements[0].componentName - ].activeChildren; - let u2string = u2[0]; - let u2math = me.fromAst( - stateVariables[u2[1].componentName].stateValues.value, - ); - expect(u2math.equals(option[u2string])).eq(true); - let repeatumath = me.fromAst( - stateVariables[ - stateVariables[ - stateVariables["/repeat"].activeChildren[4] - .componentName - ].activeChildren[1].componentName - ].stateValues.value, - ); - expect(repeatumath.equals(option[u2string])).eq(true); - }); - }); - - it("variant names specified, select single", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

Selected variable: - -

- -

Selected variable repeated: $x{name="x2"}

-

Selected variable repeated again: $_select1{name="x3"}

- `, - requestedVariantIndex: 2, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - // let variantName = stateVariables['/x'].sharedParameters.variantName; - // let expectedx = variantName.substring(0, 1); - let expectedx = "b"; - - let x = stateVariables["/x"].stateValues.value; - - expect(x).eq(expectedx); - - let xorig = - stateVariables[ - stateVariables[ - stateVariables["/_select1"].replacements[0] - .componentName - ].replacements[0].componentName - ].stateValues.value; - expect(xorig).eq(expectedx); - - let x2 = stateVariables["/x2"].stateValues.value; - expect(x2).eq(expectedx); - - let x3 = - stateVariables[ - stateVariables[ - stateVariables["/x3"].replacements[0].componentName - ].replacements[0].componentName - ].stateValues.value; - expect(x3).eq(expectedx); - }); - }); - - it("variant names specified, select multiple", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

Selected variables: - - - -

- -

Selected first variable: $x{name="x2"}

-

Selected second variable: $y{name="y2"}

-

Selected third variable: $z{name="z2"}

-

Selected variables repeated: $_select1{name="s2"}

- - `, - requestedVariantIndex: 3, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let variantMap = { - avocado: ["d", "a", "a"], - broccoli: ["e", "a", "b"], - carrot: ["d", "c", "b"], - dill: ["d", "e", "b"], - eggplant: ["c", "c", "e"], - }; - - // let variantName = stateVariables['/x'].sharedParameters.variantName; - let variantName = "carrot"; - let variantVars = variantMap[variantName]; - - let x = stateVariables["/x"].stateValues.value; - - expect(variantVars.includes(x)).eq(true); - variantVars.splice(variantVars.indexOf(x), 1); - - let y = stateVariables["/y"].stateValues.value; - expect(variantVars.includes(y)).eq(true); - variantVars.splice(variantVars.indexOf(y), 1); - - let z = stateVariables["/z"].stateValues.value; - expect(z).eq(variantVars[0]); - - let xorig = - stateVariables[ - stateVariables[ - stateVariables["/_select1"].replacements[0] - .componentName - ].replacements[0].componentName - ].stateValues.value; - expect(xorig).eq(x); - let yorig = - stateVariables[ - stateVariables[ - stateVariables["/_select1"].replacements[1] - .componentName - ].replacements[0].componentName - ].stateValues.value; - expect(yorig).eq(y); - let zorig = - stateVariables[ - stateVariables[ - stateVariables["/_select1"].replacements[2] - .componentName - ].replacements[0].componentName - ].stateValues.value; - expect(zorig).eq(z); - - let x2 = stateVariables["/x2"].stateValues.value; - expect(x2).eq(x); - let y2 = stateVariables["/y2"].stateValues.value; - expect(y2).eq(y); - let z2 = stateVariables["/z2"].stateValues.value; - expect(z2).eq(z); - - let x3 = - stateVariables[ - stateVariables[ - stateVariables["/s2"].replacements[0].componentName - ].replacements[0].componentName - ].stateValues.value; - expect(x3).eq(x); - let y3 = - stateVariables[ - stateVariables[ - stateVariables["/s2"].replacements[1].componentName - ].replacements[0].componentName - ].stateValues.value; - expect(y3).eq(y); - let z3 = - stateVariables[ - stateVariables[ - stateVariables["/s2"].replacements[2].componentName - ].replacements[0].componentName - ].stateValues.value; - expect(z3).eq(z); - }); - }); - - it("select math as sugared string", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let options = ["x^2", "x/y", "u", "a", "b-c", "s+t", "mn", "-1"].map( - (x) => me.fromText(x), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathsSoFar = []; - for (let ind = 1; ind <= 5; ind++) { - let math = me.fromAst( - stateVariables["/m" + ind].stateValues.value, - ); - expect(options.some((x) => x.equalsViaSyntax(math))).eq(true); - expect(mathsSoFar.some((x) => x.equalsViaSyntax(math))).eq( - false, - ); - mathsSoFar.push(math); - } - }); - }); - - it("select math as sugared string, no type specified", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let options = ["x^2", "x/y", "u", "a", "b-c", "s+t", "mn", "-1"].map( - (x) => me.fromText(x), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathsSoFar = []; - for (let ind = 1; ind <= 5; ind++) { - let math = me.fromAst( - stateVariables["/m" + ind].stateValues.value, - ); - expect(options.some((x) => x.equalsViaSyntax(math))).eq(true); - expect(mathsSoFar.some((x) => x.equalsViaSyntax(math))).eq( - false, - ); - mathsSoFar.push(math); - } - }); - }); - - it("select math as sugared strings and macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - x - y - 7 - -3 - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let options = ["7x^2", "(-3)x/y", "u-(-3)", "7", "x-c", "y"].map((x) => - me.fromText(x), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathsSoFar = []; - for (let ind = 1; ind <= 6; ind++) { - let comp = stateVariables["/m" + ind]; - let math; - if (comp.componentType === "math") { - math = me.fromAst(comp.stateValues.value); - } else { - math = me.fromAst( - stateVariables[comp.replacements[0].componentName] - .stateValues.value, - ); - } - expect(options.some((x) => x.equalsViaSyntax(math))).eq(true); - expect(mathsSoFar.some((x) => x.equalsViaSyntax(math))).eq( - false, - ); - mathsSoFar.push(math); - } - }); - }); - - it("select text as sugared string", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let wordsSoFar = []; - for (let ind = 1; ind <= 5; ind++) { - let word = stateVariables["/w" + ind].stateValues.value; - expect( - [ - "Lorem", - "ipsum", - "dolor", - "sit", - "amet", - "consectetur", - "adipiscing", - "elit", - ].includes(word), - ).eq(true); - expect(wordsSoFar.includes(word)).eq(false); - wordsSoFar.push(word); - } - }); - }); - - it("select text as sugared strings and macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - amet - consectetur - dolor - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let wordsSoFar = []; - for (let ind = 1; ind <= 5; ind++) { - let comp = stateVariables["/w" + ind]; - let word; - if (comp.componentType === "text") { - word = comp.stateValues.value; - } else { - word = - stateVariables[comp.replacements[0].componentName] - .stateValues.value; - } - - expect( - [ - "Lorem", - "ipsum dolor", - "sit", - "amet", - "consectetur adipiscing", - ].includes(word), - ).eq(true); - expect(wordsSoFar.includes(word)).eq(false); - wordsSoFar.push(word); - } - }); - }); - - it("select number as sugared string", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 10; ind++) { - let num = stateVariables["/n" + ind].stateValues.value; - expect([2, 3, 5, 7, 11, 13, 17, 19].includes(num)).eq(true); - } - }); - }); - - it("select number as sugared strings and macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - 5 - -7 - 6+2 - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 6; ind++) { - let comp = stateVariables["/n" + ind]; - let num; - if (comp.componentType === "number") { - num = comp.stateValues.value; - } else { - num = - stateVariables[comp.replacements[0].componentName] - .stateValues.value; - } - expect([2, -2, -5, 5, -8, 8].includes(num)).eq(true); - } - }); - }); - - it("select boolean as sugared string", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let foundTrue = false, - foundFalse = false; - for (let ind = 1; ind <= 20; ind++) { - let bool = stateVariables["/b" + ind].stateValues.value; - expect([true, false].includes(bool)).eq(true); - if (bool === true) { - foundTrue = true; - } else { - foundFalse = true; - } - } - expect(foundTrue).be.true; - expect(foundFalse).be.true; - }); - }); - - it("select boolean as sugared strings and macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - true - false - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let foundTrue = false, - foundFalse = false; - for (let ind = 1; ind <= 20; ind++) { - let comp = stateVariables["/b" + ind]; - let bool; - if (comp.componentType === "boolean") { - bool = comp.stateValues.value; - } else { - bool = - stateVariables[comp.replacements[0].componentName] - .stateValues.value; - } - expect([true, false].includes(bool)).eq(true); - if (bool === true) { - foundTrue = true; - } else { - foundFalse = true; - } - } - expect(foundTrue).be.true; - expect(foundFalse).be.true; - }); - }); - - it("select invalid type with sugared string, becomes math with warning", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let options = ["x^2", "x/y", "u", "a", "b-c", "s+t", "mn", "-1"].map( - (x) => me.fromText(x), - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let mathsSoFar = []; - for (let ind = 1; ind <= 5; ind++) { - let math = me.fromAst( - stateVariables["/m" + ind].stateValues.value, - ); - expect(options.some((x) => x.equalsViaSyntax(math))).eq(true); - expect(mathsSoFar.some((x) => x.equalsViaSyntax(math))).eq( - false, - ); - mathsSoFar.push(math); - } - }); - - cy.window().then(async (win) => { - let errorWarnings = await win.returnErrorWarnings1(); - - expect(errorWarnings.errors.length).eq(0); - expect(errorWarnings.warnings.length).eq(1); - - expect(errorWarnings.warnings[0].message).contain( - "Invalid type for select: nothing", - ); - expect(errorWarnings.warnings[0].level).eq(1); - expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(4); - expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(5); - expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(6); - expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(13); - }); - }); - - it("select weighted", () => { - // TODO: this test seems to fail with num Y < 17 once in awhile - // even though it should fail less than 0.1% of the time - // Is there a flaw? - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", `a`); - - let numX = 0, - numY = 0, - numZ = 0; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 0; ind < 200; ind++) { - let theText = - stateVariables[ - stateVariables[ - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[ind] - .componentName - ].replacements[1].componentName - ].replacements[0].componentName - ].replacements[0].componentName - ]; - let x = theText.stateValues.value; - if (x === "z") { - numZ++; - } else if (x === "y") { - numY++; - } else { - numX++; - } - } - }); - - cy.window().then(async (win) => { - expect(numX).greaterThan(0); - expect(numX).lessThan(15); - expect(numY).greaterThan(17); - expect(numY).lessThan(50); - expect(numZ).greaterThan(140); - }); - }); - - it("select weighted with replacement", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - `, - requestedVariantIndex: 0, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let numX = 0, - numY = 0, - numZ = 0; - let selectReplacements = stateVariables["/_select1"].replacements; - for (let ind = 0; ind < 200; ind++) { - let x = - stateVariables[ - stateVariables[selectReplacements[ind].componentName] - .replacements[0].componentName - ].stateValues.value; - if (x === "x") { - numX++; - } else if (x === "y") { - numY++; - } else { - numZ++; - } - } - expect(numX).greaterThan(0); - expect(numX).lessThan(15); - expect(numY).greaterThan(20); - expect(numY).lessThan(50); - expect(numZ).greaterThan(150); - }); - }); - - it("select weighted without replacement", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", `a`); - - let numX = 0, - numY = 0, - numZ = 0, - numUVW = 0; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - for (let ind = 0; ind < 200; ind++) { - let theSelect = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[ind] - .componentName - ].replacements[1].componentName - ]; - let theText1 = - stateVariables[ - stateVariables[theSelect.replacements[0].componentName] - .replacements[0].componentName - ]; - let x = theText1.stateValues.value; - - if (x === "z") { - numZ++; - } else if (x === "y") { - numY++; - } else if (x === "x") { - numX++; - } else { - numUVW++; - } - let theText2 = - stateVariables[ - stateVariables[theSelect.replacements[1].componentName] - .replacements[0].componentName - ]; - let y = theText2.stateValues.value; - if (y === "z") { - numZ++; - } else if (y === "y") { - numY++; - } else if (y === "x") { - numX++; - } else { - numUVW++; - } - } - }); - - cy.window().then(async (win) => { - expect(numUVW).greaterThan(0); - expect(numUVW).lessThan(20); - expect(numX).greaterThan(150); - expect(numY).greaterThan(10); - expect(numY).lessThan(50); - expect(numZ).greaterThan(170); - }); - }); - - it("references to internal assignnames", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - a e i o u$q{name="q2"}$r{name="r2"}

- - - - - -

Selected options repeated

- $q{name="q2"} - $r{name="r2"} - $s{name="s2"} - $t{name="t2"} - $u{name="u2"} - $v{name="v2"} - $w{name="w2"} - -

Copy q and r and their copies from within selected options

-

$(q/q{name="qq"})$(q/r{name="qr"})$(q/q2{name="qq2"})$(q/r2{name="qr2"})

-

$(r/q{name="rq"})$(r/r{name="rr"})$(r/q2{name="rq2"})$(r/r2{name="rr2"})

-

$(s/q{name="sq"})$(s/r{name="sr"})$(s/q2{name="sq2"})$(s/r2{name="sr2"})

-

$(t/q{name="tq"})$(t/r{name="tr"})$(t/q2{name="tq2"})$(t/r2{name="tr2"})

-

$(u/q{name="uq"})$(u/r{name="ur"})$(u/q2{name="uq2"})$(u/r2{name="ur2"})

-

$(v/q{name="vq"})$(v/r{name="vr"})$(v/q2{name="vq2"})$(v/r2{name="vr2"})

-

$(w/q{name="wq"})$(w/r{name="wr"})$(w/q2{name="wq2"})$(w/r2{name="wr2"})

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let qs = stateVariables["/q"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let rs = stateVariables["/r"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let ss = stateVariables["/s"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let ts = stateVariables["/t"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let us = stateVariables["/u"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let vs = stateVariables["/v"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let ws = stateVariables["/w"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - - let q2s = stateVariables["/q2"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let r2s = stateVariables["/r2"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let s2s = stateVariables["/s2"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let t2s = stateVariables["/t2"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let u2s = stateVariables["/u2"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let v2s = stateVariables["/v2"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let w2s = stateVariables["/w2"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - - expect(q2s).eqls(qs); - expect(r2s).eqls(rs); - expect(s2s).eqls(ss); - expect(t2s).eqls(ts); - expect(u2s).eqls(us); - expect(v2s).eqls(vs); - expect(w2s).eqls(ws); - - let q3s = [ - stateVariables["/qq"].stateValues.value, - stateVariables["/qr"].stateValues.value, - stateVariables["/qq2"].stateValues.value, - stateVariables["/qr2"].stateValues.value, - ]; - let r3s = [ - stateVariables["/rq"].stateValues.value, - stateVariables["/rr"].stateValues.value, - stateVariables["/rq2"].stateValues.value, - stateVariables["/rr2"].stateValues.value, - ]; - let s3s = [ - stateVariables["/sq"].stateValues.value, - stateVariables["/sr"].stateValues.value, - stateVariables["/sq2"].stateValues.value, - stateVariables["/sr2"].stateValues.value, - ]; - let t3s = [ - stateVariables["/tq"].stateValues.value, - stateVariables["/tr"].stateValues.value, - stateVariables["/tq2"].stateValues.value, - stateVariables["/tr2"].stateValues.value, - ]; - let u3s = [ - stateVariables["/uq"].stateValues.value, - stateVariables["/ur"].stateValues.value, - stateVariables["/uq2"].stateValues.value, - stateVariables["/ur2"].stateValues.value, - ]; - let v3s = [ - stateVariables["/vq"].stateValues.value, - stateVariables["/vr"].stateValues.value, - stateVariables["/vq2"].stateValues.value, - stateVariables["/vr2"].stateValues.value, - ]; - let w3s = [ - stateVariables["/wq"].stateValues.value, - stateVariables["/wr"].stateValues.value, - stateVariables["/wq2"].stateValues.value, - stateVariables["/wr2"].stateValues.value, - ]; - - expect(q3s).eqls(qs); - expect(r3s).eqls(rs); - expect(s3s).eqls(ss); - expect(t3s).eqls(ts); - expect(u3s).eqls(us); - expect(v3s).eqls(vs); - expect(w3s).eqls(ws); - }); - }); - - it("references to internal assignnames, newnamespaces", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - a e i o u$(s/q{name="q2"})$(s/r{name="r2"})

- - - - -

Selected options repeated

- $q{name="q2"} - $r{name="r2"} - $s{name="s2"} - $t{name="t2"} - $u{name="u2"} - $v{name="v2"} - $w{name="w2"} - -

Selected options repeated, no p

-

$(q/s{name="q3"})

-

$(r/s{name="r3"})

-

$(s/s{name="s3"})

-

$(t/s{name="t3"})

-

$(u/s{name="u3"})

-

$(v/s{name="v3"})

-

$(w/s{name="w3"})

- -

Copy q and r from within selected options

-

$(q/s/q{name="qq"})$(q/s/r{name="qr"})$(q/q2{name="qq2"})$(q/r2{name="qr2"})

-

$(r/s/q{name="rq"})$(r/s/r{name="rr"})$(r/q2{name="rq2"})$(r/r2{name="rr2"})

-

$(s/s/q{name="sq"})$(s/s/r{name="sr"})$(s/q2{name="sq2"})$(s/r2{name="sr2"})

-

$(t/s/q{name="tq"})$(t/s/r{name="tr"})$(t/q2{name="tq2"})$(t/r2{name="tr2"})

-

$(u/s/q{name="uq"})$(u/s/r{name="ur"})$(u/q2{name="uq2"})$(u/r2{name="ur2"})

-

$(v/s/q{name="vq"})$(v/s/r{name="vr"})$(v/q2{name="vq2"})$(v/r2{name="vr2"})

-

$(w/s/q{name="wq"})$(w/s/r{name="wr"})$(w/q2{name="wq2"})$(w/r2{name="wr2"})

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let qs = stateVariables["/q"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let rs = stateVariables["/r"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let ss = stateVariables["/s"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let ts = stateVariables["/t"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let us = stateVariables["/u"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let vs = stateVariables["/v"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let ws = stateVariables["/w"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - - let q2s = stateVariables["/q2"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let r2s = stateVariables["/r2"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let s2s = stateVariables["/s2"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let t2s = stateVariables["/t2"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let u2s = stateVariables["/u2"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let v2s = stateVariables["/v2"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let w2s = stateVariables["/w2"].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - - expect(q2s).eqls(qs); - expect(r2s).eqls(rs); - expect(s2s).eqls(ss); - expect(t2s).eqls(ts); - expect(u2s).eqls(us); - expect(v2s).eqls(vs); - expect(w2s).eqls(ws); - - let q3s = stateVariables["/q3"].replacements - .map((x) => stateVariables[x.componentName]) - .map((x) => - x.replacements - ? stateVariables[x.replacements[0].componentName] - .stateValues.value - : x.stateValues.value, - ); - let r3s = stateVariables["/r3"].replacements - .map((x) => stateVariables[x.componentName]) - .map((x) => - x.replacements - ? stateVariables[x.replacements[0].componentName] - .stateValues.value - : x.stateValues.value, - ); - let s3s = stateVariables["/s3"].replacements - .map((x) => stateVariables[x.componentName]) - .map((x) => - x.replacements - ? stateVariables[x.replacements[0].componentName] - .stateValues.value - : x.stateValues.value, - ); - let t3s = stateVariables["/t3"].replacements - .map((x) => stateVariables[x.componentName]) - .map((x) => - x.replacements - ? stateVariables[x.replacements[0].componentName] - .stateValues.value - : x.stateValues.value, - ); - let u3s = stateVariables["/u3"].replacements - .map((x) => stateVariables[x.componentName]) - .map((x) => - x.replacements - ? stateVariables[x.replacements[0].componentName] - .stateValues.value - : x.stateValues.value, - ); - let v3s = stateVariables["/v3"].replacements - .map((x) => stateVariables[x.componentName]) - .map((x) => - x.replacements - ? stateVariables[x.replacements[0].componentName] - .stateValues.value - : x.stateValues.value, - ); - let w3s = stateVariables["/w3"].replacements - .map((x) => stateVariables[x.componentName]) - .map((x) => - x.replacements - ? stateVariables[x.replacements[0].componentName] - .stateValues.value - : x.stateValues.value, - ); - - expect(q3s).eqls(qs.slice(0, 2)); - expect(r3s).eqls(rs.slice(0, 2)); - expect(s3s).eqls(ss.slice(0, 2)); - expect(t3s).eqls(ts.slice(0, 2)); - expect(u3s).eqls(us.slice(0, 2)); - expect(v3s).eqls(vs.slice(0, 2)); - expect(w3s).eqls(ws.slice(0, 2)); - - let q4s = [ - stateVariables["/qq"].stateValues.value, - stateVariables["/qr"].stateValues.value, - stateVariables["/qq2"].stateValues.value, - stateVariables["/qr2"].stateValues.value, - ]; - let r4s = [ - stateVariables["/rq"].stateValues.value, - stateVariables["/rr"].stateValues.value, - stateVariables["/rq2"].stateValues.value, - stateVariables["/rr2"].stateValues.value, - ]; - let s4s = [ - stateVariables["/sq"].stateValues.value, - stateVariables["/sr"].stateValues.value, - stateVariables["/sq2"].stateValues.value, - stateVariables["/sr2"].stateValues.value, - ]; - let t4s = [ - stateVariables["/tq"].stateValues.value, - stateVariables["/tr"].stateValues.value, - stateVariables["/tq2"].stateValues.value, - stateVariables["/tr2"].stateValues.value, - ]; - let u4s = [ - stateVariables["/uq"].stateValues.value, - stateVariables["/ur"].stateValues.value, - stateVariables["/uq2"].stateValues.value, - stateVariables["/ur2"].stateValues.value, - ]; - let v4s = [ - stateVariables["/vq"].stateValues.value, - stateVariables["/vr"].stateValues.value, - stateVariables["/vq2"].stateValues.value, - stateVariables["/vr2"].stateValues.value, - ]; - let w4s = [ - stateVariables["/wq"].stateValues.value, - stateVariables["/wr"].stateValues.value, - stateVariables["/wq2"].stateValues.value, - stateVariables["/wr2"].stateValues.value, - ]; - - expect(q4s).eqls(qs); - expect(r4s).eqls(rs); - expect(s4s).eqls(ss); - expect(t4s).eqls(ts); - expect(u4s).eqls(us); - expect(v4s).eqls(vs); - expect(w4s).eqls(ws); - }); - }); - - // can no longer reference between named grandchildren using their original names - it.skip("references to internal assignnames, named grandchildren", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 - a e i o u$q{name="q2"}$r{name="r2"}

-

a z$q{name="q2"}$r{name="r2"}

- - -

Selected options repeated

-

$q{name="q2"}

-

$r{name="r2"}

-

$s{name="s2"}

-

$t{name="t2"}

-

$u{name="u2"}

- -

Copy x/q and x/r and their copies from within selected options

-

$(q/q{name="qq2"})$(q/r{name="qr2"})$qq{name="qq3"}$qr{name="qr3"}

-

$(r/q{name="rq2"})$(r/r{name="rr2"})$rq{name="rq3"}$rr{name="rr3"}

-

$(s/q{name="sq2"})$(s/r{name="sr2"})$sq{name="sq3"}$sr{name="sr3"}

-

$(t/q{name="tq2"})$(t/r{name="tr2"})$tq{name="tq3"}$tr{name="tr3"}

-

$(u/q{name="uq2"})$(u/r{name="ur2"})$uq{name="uq3"}$ur{name="ur3"}

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/u\\/r")) - .invoke("text") - .then((text) => { - expect(text.length).equal(1); - }); - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let qs = stateVariables["/q"].replacements.map( - (x) => x.stateValues.value, - ); - let rs = stateVariables["/r"].replacements.map( - (x) => x.stateValues.value, - ); - let ss = stateVariables["/s"].replacements.map( - (x) => x.stateValues.value, - ); - let ts = stateVariables["/t"].replacements.map( - (x) => x.stateValues.value, - ); - let us = stateVariables["/u"].replacements.map( - (x) => x.stateValues.value, - ); - - let q2s = stateVariables["/q2"].replacements.map( - (x) => x.stateValues.value, - ); - let r2s = stateVariables["/r2"].replacements.map( - (x) => x.stateValues.value, - ); - let s2s = stateVariables["/s2"].replacements.map( - (x) => x.stateValues.value, - ); - let t2s = stateVariables["/t2"].replacements.map( - (x) => x.stateValues.value, - ); - let u2s = stateVariables["/u2"].replacements.map( - (x) => x.stateValues.value, - ); - - expect(q2s).eqls(qs); - expect(r2s).eqls(rs); - expect(s2s).eqls(ss); - expect(t2s).eqls(ts); - expect(u2s).eqls(us); - - let q3s = [ - stateVariables[ - stateVariables["/qq2"].replacements[0].componentName - ].stateValues.value, - stateVariables[ - stateVariables["/qr2"].replacements[0].componentName - ].stateValues.value, - ]; - let q4s = [ - stateVariables[ - stateVariables["/qq3"].replacements[0].componentName - ].stateValues.value, - stateVariables[ - stateVariables["/qr3"].replacements[0].componentName - ].stateValues.value, - ]; - let r3s = [ - stateVariables[ - stateVariables["/rq2"].replacements[0].componentName - ].stateValues.value, - stateVariables[ - stateVariables["/rr2"].replacements[0].componentName - ].stateValues.value, - ]; - let r4s = [ - stateVariables[ - stateVariables["/rq3"].replacements[0].componentName - ].stateValues.value, - stateVariables[ - stateVariables["/rr3"].replacements[0].componentName - ].stateValues.value, - ]; - let s3s = [ - stateVariables[ - stateVariables["/sq2"].replacements[0].componentName - ].stateValues.value, - stateVariables[ - stateVariables["/sr2"].replacements[0].componentName - ].stateValues.value, - ]; - let s4s = [ - stateVariables[ - stateVariables["/sq3"].replacements[0].componentName - ].stateValues.value, - stateVariables[ - stateVariables["/sr3"].replacements[0].componentName - ].stateValues.value, - ]; - let t3s = [ - stateVariables[ - stateVariables["/tq2"].replacements[0].componentName - ].stateValues.value, - stateVariables[ - stateVariables["/tr2"].replacements[0].componentName - ].stateValues.value, - ]; - let t4s = [ - stateVariables[ - stateVariables["/tq3"].replacements[0].componentName - ].stateValues.value, - stateVariables[ - stateVariables["/tr3"].replacements[0].componentName - ].stateValues.value, - ]; - let u3s = [ - stateVariables[ - stateVariables["/uq2"].replacements[0].componentName - ].stateValues.value, - stateVariables[ - stateVariables["/ur2"].replacements[0].componentName - ].stateValues.value, - ]; - let u4s = [ - stateVariables[ - stateVariables["/uq3"].replacements[0].componentName - ].stateValues.value, - stateVariables[ - stateVariables["/ur3"].replacements[0].componentName - ].stateValues.value, - ]; - - expect(q3s).eqls(qs); - expect(r3s).eqls(rs); - expect(s3s).eqls(ss); - expect(t3s).eqls(ts); - expect(u3s).eqls(us); - - expect(q4s).eqls(qs); - expect(r4s).eqls(rs); - expect(s4s).eqls(ss); - expect(t4s).eqls(ts); - expect(u4s).eqls(us); - }); - }); - - // can no longer reference between named grandchildren using their original names - it.skip("references to internal assignnames, newnamespaces, named grandchildren", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 - a e i o u$(a/q{name="q2"})$(a/r{name="r2"})

-

a z$(b/q{name="q2"})$(b/r{name="r2"})

- - -

Selected options repeated

-

$q{name="q2"}

-

$r{name="r2"}

-

$s{name="s2"}

-

$t{name="t2"}

-

$u{name="u2"}

- -

Copy x/q and x/r and their copies from within selected options

-

$(q/q{name="qq2"})$(q/r{name="qr2"})$qq{name="qq3"}$qr{name="qr3"}

-

$(r/q{name="rq2"})$(r/r{name="rr2"})$rq{name="rq3"}$rr{name="rr3"}

-

$(s/q{name="sq2"})$(s/r{name="sr2"})$sq{name="sq3"}$sr{name="sr3"}

-

$(t/q{name="tq2"})$(t/r{name="tr2"})$tq{name="tq3"}$tr{name="tr3"}

-

$(u/q{name="uq2"})$(u/r{name="ur2"})$uq{name="uq3"}$ur{name="ur3"}

- - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/u\\/r")) - .invoke("text") - .then((text) => { - expect(text.length).equal(1); - }); - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let qs = stateVariables["/q"].replacements.map( - (x) => x.stateValues.value, - ); - let rs = stateVariables["/r"].replacements.map( - (x) => x.stateValues.value, - ); - let ss = stateVariables["/s"].replacements.map( - (x) => x.stateValues.value, - ); - let ts = stateVariables["/t"].replacements.map( - (x) => x.stateValues.value, - ); - let us = stateVariables["/u"].replacements.map( - (x) => x.stateValues.value, - ); - - let q2s = stateVariables["/q2"].replacements.map( - (x) => x.stateValues.value, - ); - let r2s = stateVariables["/r2"].replacements.map( - (x) => x.stateValues.value, - ); - let s2s = stateVariables["/s2"].replacements.map( - (x) => x.stateValues.value, - ); - let t2s = stateVariables["/t2"].replacements.map( - (x) => x.stateValues.value, - ); - let u2s = stateVariables["/u2"].replacements.map( - (x) => x.stateValues.value, - ); - - expect(q2s).eqls(qs); - expect(r2s).eqls(rs); - expect(s2s).eqls(ss); - expect(t2s).eqls(ts); - expect(u2s).eqls(us); - - let q3s = [ - stateVariables[ - stateVariables["/qq2"].replacements[0].componentName - ].stateValues.value, - stateVariables[ - stateVariables["/qr2"].replacements[0].componentName - ].stateValues.value, - ]; - let q4s = [ - stateVariables[ - stateVariables["/qq3"].replacements[0].componentName - ].stateValues.value, - stateVariables[ - stateVariables["/qr3"].replacements[0].componentName - ].stateValues.value, - ]; - let r3s = [ - stateVariables[ - stateVariables["/rq2"].replacements[0].componentName - ].stateValues.value, - stateVariables[ - stateVariables["/rr2"].replacements[0].componentName - ].stateValues.value, - ]; - let r4s = [ - stateVariables[ - stateVariables["/rq3"].replacements[0].componentName - ].stateValues.value, - stateVariables[ - stateVariables["/rr3"].replacements[0].componentName - ].stateValues.value, - ]; - let s3s = [ - stateVariables[ - stateVariables["/sq2"].replacements[0].componentName - ].stateValues.value, - stateVariables[ - stateVariables["/sr2"].replacements[0].componentName - ].stateValues.value, - ]; - let s4s = [ - stateVariables[ - stateVariables["/sq3"].replacements[0].componentName - ].stateValues.value, - stateVariables[ - stateVariables["/sr3"].replacements[0].componentName - ].stateValues.value, - ]; - let t3s = [ - stateVariables[ - stateVariables["/tq2"].replacements[0].componentName - ].stateValues.value, - stateVariables[ - stateVariables["/tr2"].replacements[0].componentName - ].stateValues.value, - ]; - let t4s = [ - stateVariables[ - stateVariables["/tq3"].replacements[0].componentName - ].stateValues.value, - stateVariables[ - stateVariables["/tr3"].replacements[0].componentName - ].stateValues.value, - ]; - let u3s = [ - stateVariables[ - stateVariables["/uq2"].replacements[0].componentName - ].stateValues.value, - stateVariables[ - stateVariables["/ur2"].replacements[0].componentName - ].stateValues.value, - ]; - let u4s = [ - stateVariables[ - stateVariables["/uq3"].replacements[0].componentName - ].stateValues.value, - stateVariables[ - stateVariables["/ur3"].replacements[0].componentName - ].stateValues.value, - ]; - - expect(q3s).eqls(qs); - expect(r3s).eqls(rs); - expect(s3s).eqls(ss); - expect(t3s).eqls(ts); - expect(u3s).eqls(us); - - expect(q4s).eqls(qs); - expect(r4s).eqls(rs); - expect(s4s).eqls(ss); - expect(t4s).eqls(ts); - expect(u4s).eqls(us); - }); - }); - - it("references to select of selects", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - a e i o u - - - -

Selected options repeated

-

$q{name="q2"}

-

$r{name="r2"}

-

$s{name="s2"}

-

$t{name="t2"}

-

$u{name="u2"}

- -

Copy x/q and x/r

-

$(q/q{name="qq"})$(q/r{name="qr"})

-

$(r/q{name="rq"})$(r/r{name="rr"})

-

$(s/q{name="sq"})$(s/r{name="sr"})

-

$(t/q{name="tq"})$(t/r{name="tr"})

-

$(u/q{name="uq"})$(u/r{name="ur"})

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let qs = stateVariables["/q"].replacements - .map((x) => stateVariables[x.componentName]) - .map((x) => - x.replacements - ? stateVariables[x.replacements[0].componentName] - .stateValues.value - : x.stateValues.value, - ); - let rs = stateVariables["/r"].replacements - .map((x) => stateVariables[x.componentName]) - .map((x) => - x.replacements - ? stateVariables[x.replacements[0].componentName] - .stateValues.value - : x.stateValues.value, - ); - let ss = stateVariables["/s"].replacements - .map((x) => stateVariables[x.componentName]) - .map((x) => - x.replacements - ? stateVariables[x.replacements[0].componentName] - .stateValues.value - : x.stateValues.value, - ); - let ts = stateVariables["/t"].replacements - .map((x) => stateVariables[x.componentName]) - .map((x) => - x.replacements - ? stateVariables[x.replacements[0].componentName] - .stateValues.value - : x.stateValues.value, - ); - let us = stateVariables["/u"].replacements - .map((x) => stateVariables[x.componentName]) - .map((x) => - x.replacements - ? stateVariables[x.replacements[0].componentName] - .stateValues.value - : x.stateValues.value, - ); - - let q2s = stateVariables["/q2"].replacements - .map((x) => stateVariables[x.componentName]) - .map((x) => - x.replacements - ? stateVariables[x.replacements[0].componentName] - .stateValues.value - : x.stateValues.value, - ); - let r2s = stateVariables["/r2"].replacements - .map((x) => stateVariables[x.componentName]) - .map((x) => - x.replacements - ? stateVariables[x.replacements[0].componentName] - .stateValues.value - : x.stateValues.value, - ); - let s2s = stateVariables["/s2"].replacements - .map((x) => stateVariables[x.componentName]) - .map((x) => - x.replacements - ? stateVariables[x.replacements[0].componentName] - .stateValues.value - : x.stateValues.value, - ); - let t2s = stateVariables["/t2"].replacements - .map((x) => stateVariables[x.componentName]) - .map((x) => - x.replacements - ? stateVariables[x.replacements[0].componentName] - .stateValues.value - : x.stateValues.value, - ); - let u2s = stateVariables["/u2"].replacements - .map((x) => stateVariables[x.componentName]) - .map((x) => - x.replacements - ? stateVariables[x.replacements[0].componentName] - .stateValues.value - : x.stateValues.value, - ); - - expect(q2s).eqls(qs); - expect(r2s).eqls(rs); - expect(s2s).eqls(ss); - expect(t2s).eqls(ts); - expect(u2s).eqls(us); - - let q3s = [ - stateVariables["/qq"].stateValues.value, - stateVariables["/qr"].stateValues.value, - ]; - let r3s = [ - stateVariables["/rq"].stateValues.value, - stateVariables["/rr"].stateValues.value, - ]; - let s3s = [ - stateVariables["/sq"].stateValues.value, - stateVariables["/sr"].stateValues.value, - ]; - let t3s = [ - stateVariables["/tq"].stateValues.value, - stateVariables["/tr"].stateValues.value, - ]; - let u3s = [ - stateVariables["/uq"].stateValues.value, - stateVariables["/ur"].stateValues.value, - ]; - - expect(q3s).eqls(qs); - expect(r3s).eqls(rs); - expect(s3s).eqls(ss); - expect(t3s).eqls(ts); - expect(u3s).eqls(us); - }); - }); - - it("references to select of selects of selects", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - - - - -

Selected options repeated

-

$q{name="q2"}

-

$r{name="r2"}

-

$s{name="s2"}

- -

Copy x/q, x/r, x/s

-

$(q/q{name="qq"})$(q/r{name="qr"})$(q/s{name="qs"})

-

$(r/q{name="rq"})$(r/r{name="rr"})$(r/s{name="rs"})

-

$(s/q{name="sq"})$(s/r{name="sr"})$(s/s{name="ss"})

- -

Copy x/x/q, x/x/r

-

$(q/q/q{name="qqq"})$(q/q/r{name="qqr"})$(q/r/q{name="qrq"})$(q/r/r{name="qrr"})$(q/s/q{name="qsq"})$(q/s/r{name="qsr"})

-

$(r/q/q{name="rqq"})$(r/q/r{name="rqr"})$(r/r/q{name="rrq"})$(r/r/r{name="rrr"})$(r/s/q{name="rsq"})$(r/s/r{name="rsr"})

-

$(s/q/q{name="sqq"})$(s/q/r{name="sqr"})$(s/r/q{name="srq"})$(s/r/r{name="srr"})$(s/s/q{name="ssq"})$(s/s/r{name="ssr"})

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let qs = [ - "/q/q/q", - "/q/q/r", - "/q/r/q", - "/q/r/r", - "/q/s/q", - "/q/s/r", - ].map((x) => - stateVariables[x].replacements - ? stateVariables[ - stateVariables[x].replacements[0].componentName - ].stateValues.value - : stateVariables[x].stateValues.value, - ); - let rs = [ - "/r/q/q", - "/r/q/r", - "/r/r/q", - "/r/r/r", - "/r/s/q", - "/r/s/r", - ].map((x) => - stateVariables[x].replacements - ? stateVariables[ - stateVariables[x].replacements[0].componentName - ].stateValues.value - : stateVariables[x].stateValues.value, - ); - let ss = [ - "/s/q/q", - "/s/q/r", - "/s/r/q", - "/s/r/r", - "/s/s/q", - "/s/s/r", - ].map((x) => - stateVariables[x].replacements - ? stateVariables[ - stateVariables[x].replacements[0].componentName - ].stateValues.value - : stateVariables[x].stateValues.value, - ); - - cy.get(cesc("#\\/pq2")) - .invoke("text") - .then((text) => { - expect(text.replace(/, /g, "")).eq(qs.join("")); - }); - cy.get(cesc("#\\/pr2")) - .invoke("text") - .then((text) => { - expect(text.replace(/, /g, "")).eq(rs.join("")); - }); - cy.get(cesc("#\\/ps2")) - .invoke("text") - .then((text) => { - expect(text.replace(/, /g, "")).eq(ss.join("")); - }); - - cy.get(cesc("#\\/pq3")) - .invoke("text") - .then((text) => { - expect(text.replace(/, /g, "")).eq(qs.join("")); - }); - cy.get(cesc("#\\/pr3")) - .invoke("text") - .then((text) => { - expect(text.replace(/, /g, "")).eq(rs.join("")); - }); - cy.get(cesc("#\\/ps3")) - .invoke("text") - .then((text) => { - expect(text.replace(/, /g, "")).eq(ss.join("")); - }); - - cy.get(cesc("#\\/pq4")) - .invoke("text") - .then((text) => { - expect(text.replace(/, /g, "")).eq(qs.join("")); - }); - cy.get(cesc("#\\/pr4")) - .invoke("text") - .then((text) => { - expect(text.replace(/, /g, "")).eq(rs.join("")); - }); - cy.get(cesc("#\\/ps4")) - .invoke("text") - .then((text) => { - expect(text.replace(/, /g, "")).eq(ss.join("")); - }); - }); - }); - - it("references to select of selects of selects, newnamespaces", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - - - - -

Selected options repeated

-

$(a/q{name="q2"})

-

$(a/r{name="r2"})

-

$(a/s{name="s2"})

- -

Copy x/q, x/r, x/s

-

$(a/q/q{name="qq"})$(a/q/r{name="qr"})$(a/q/s{name="qs"})

-

$(a/r/q{name="rq"})$(a/r/r{name="rr"})$(a/r/s{name="rs"})

-

$(a/s/q{name="sq"})$(a/s/r{name="sr"})$(a/s/s{name="ss"})

- -

Copy x/x/q, x/x/r

-

$(a/q/q/q{name="qqq"})$(a/q/q/r{name="qqr"})$(a/q/r/q{name="qrq"})$(a/q/r/r{name="qrr"})$(a/q/s/q{name="qsq"})$(a/q/s/r{name="qsr"})

-

$(a/r/q/q{name="rqq"})$(a/r/q/r{name="rqr"})$(a/r/r/q{name="rrq"})$(a/r/r/r{name="rrr"})$(a/r/s/q{name="rsq"})$(a/r/s/r{name="rsr"})

-

$(a/s/q/q{name="sqq"})$(a/s/q/r{name="sqr"})$(a/s/r/q{name="srq"})$(a/s/r/r{name="srr"})$(a/s/s/q{name="ssq"})$(a/s/s/r{name="ssr"})

- - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let qs = [ - "/a/q/q/q", - "/a/q/q/r", - "/a/q/r/q", - "/a/q/r/r", - "/a/q/s/q", - "/a/q/s/r", - ].map((x) => - stateVariables[x].replacements - ? stateVariables[ - stateVariables[x].replacements[0].componentName - ].stateValues.value - : stateVariables[x].stateValues.value, - ); - let rs = [ - "/a/r/q/q", - "/a/r/q/r", - "/a/r/r/q", - "/a/r/r/r", - "/a/r/s/q", - "/a/r/s/r", - ].map((x) => - stateVariables[x].replacements - ? stateVariables[ - stateVariables[x].replacements[0].componentName - ].stateValues.value - : stateVariables[x].stateValues.value, - ); - let ss = [ - "/a/s/q/q", - "/a/s/q/r", - "/a/s/r/q", - "/a/s/r/r", - "/a/s/s/q", - "/a/s/s/r", - ].map((x) => - stateVariables[x].replacements - ? stateVariables[ - stateVariables[x].replacements[0].componentName - ].stateValues.value - : stateVariables[x].stateValues.value, - ); - - cy.get(cesc("#\\/pq2")) - .invoke("text") - .then((text) => { - expect(text.replace(/, /g, "")).eq(qs.join("")); - }); - cy.get(cesc("#\\/pr2")) - .invoke("text") - .then((text) => { - expect(text.replace(/, /g, "")).eq(rs.join("")); - }); - cy.get(cesc("#\\/ps2")) - .invoke("text") - .then((text) => { - expect(text.replace(/, /g, "")).eq(ss.join("")); - }); - - cy.get(cesc("#\\/pq3")) - .invoke("text") - .then((text) => { - expect(text.replace(/, /g, "")).eq(qs.join("")); - }); - cy.get(cesc("#\\/pr3")) - .invoke("text") - .then((text) => { - expect(text.replace(/, /g, "")).eq(rs.join("")); - }); - cy.get(cesc("#\\/ps3")) - .invoke("text") - .then((text) => { - expect(text.replace(/, /g, "")).eq(ss.join("")); - }); - - cy.get(cesc("#\\/pq4")) - .invoke("text") - .then((text) => { - expect(text.replace(/, /g, "")).eq(qs.join("")); - }); - cy.get(cesc("#\\/pr4")) - .invoke("text") - .then((text) => { - expect(text.replace(/, /g, "")).eq(rs.join("")); - }); - cy.get(cesc("#\\/ps4")) - .invoke("text") - .then((text) => { - expect(text.replace(/, /g, "")).eq(ss.join("")); - }); - }); - }); - - it("references to named grandchildren's children", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

Copy grandchidren

-

$a{name="a2"}

-

$b{name="b2"}

-

$c{name="c2"}

-

$d{name="d2"}

- -

Copy named children of grandchild

-

$(a/w{name="w2"})

-

$(b/v{name="v2"})

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let options = [ - { - a: "x y", - b: "3 z", - c: "x", - d: "z", - v: "z", - w: "x", - }, - { - a: "u v", - b: "3 t", - c: "u", - d: "t", - v: "t", - w: "u", - }, - ]; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let chosenChildren = stateVariables[ - stateVariables["/_select1"].replacements[0].componentName - ].replacements - .filter((x) => typeof x !== "string") - .map((x) => stateVariables[x.componentName]) - .map((v, i) => - i < 2 ? v : stateVariables[v.replacements[0].componentName], - ); - let option = - options[ - stateVariables["/_select1"].stateValues.selectedIndices[0] - - 1 - ]; - - expect( - me.fromAst(chosenChildren[0].stateValues.value).toString(), - ).eq(option.a); - expect( - me.fromAst(chosenChildren[1].stateValues.value).toString(), - ).eq(option.b); - expect( - me.fromAst(chosenChildren[2].stateValues.value).toString(), - ).eq(option.c); - expect( - me.fromAst(chosenChildren[3].stateValues.value).toString(), - ).eq(option.d); - - let a2 = me - .fromAst(stateVariables["/a2"].stateValues.value) - .toString(); - let b2 = me - .fromAst(stateVariables["/b2"].stateValues.value) - .toString(); - let c2 = me - .fromAst(stateVariables["/c2"].stateValues.value) - .toString(); - let d2 = me - .fromAst(stateVariables["/d2"].stateValues.value) - .toString(); - let v2 = me - .fromAst(stateVariables["/v2"].stateValues.value) - .toString(); - let w2 = me - .fromAst(stateVariables["/w2"].stateValues.value) - .toString(); - - expect(a2).eq(option.a); - expect(b2).eq(option.b); - expect(c2).eq(option.c); - expect(d2).eq(option.d); - expect(v2).eq(option.v); - expect(w2).eq(option.w); - }); - }); - - it("select of a map of a select, with references", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- -

- -

Copy whole select again

-

$_select1{name="s2"}

- -

Copy individual selections

-

- $j{name="j2"} - $k{name="k2"} - $l{name="l2"} -

- -

Copy individual pieces

-

- $(j/a/p{name="p1"})$(j/a/q{name="p2"})$(j/a/r{name="p3"})$(j/a/s{name="p4"})$(j/b/p{name="p5"})$(j/b/q{name="p6"})$(j/b/r{name="p7"})$(j/b/s{name="p8"}) - $(k/a/p{name="p9"})$(k/a/q{name="p10"})$(k/a/r{name="p11"})$(k/a/s{name="p12"})$(k/b/p{name="p13"})$(k/b/q{name="p14"})$(k/b/r{name="p15"})$(k/b/s{name="p16"}) - $(l/a/p{name="p17"})$(l/a/q{name="p18"})$(l/a/r{name="p19"})$(l/a/s{name="p20"})$(l/b/p{name="p21"})$(l/b/q{name="p22"})$(l/b/r{name="p23"})$(l/b/s{name="p24"}) -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let theList1 = stateVariables["/list1"].activeChildren.map((x) => - me - .fromAst(stateVariables[x.componentName].stateValues.value) - .toString(), - ); - let theList2 = stateVariables["/list2"].activeChildren.map((x) => - me - .fromAst(stateVariables[x.componentName].stateValues.value) - .toString(), - ); - let theList3 = stateVariables["/list3"].activeChildren.map((x) => - me - .fromAst(stateVariables[x.componentName].stateValues.value) - .toString(), - ); - - expect(theList2).eqls(theList1); - expect(theList3).eqls(theList1); - - let theList4 = [...Array(24).keys()].map((i) => - me - .fromAst(stateVariables["/p" + (i + 1)].stateValues.value) - .toString(), - ); - - expect(theList4).eqls(theList1); - }); - }); - - it("select of a map of a select, new namespaces", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- -

- -

Copy whole select again

-

$s{name="s2"}

- -

Copy individual selections

-

- $(s/j{name="j2"}) - $(s/k{name="k2"}) - $(s/l{name="l2"}) -

- -

Copy individual pieces

-

- $(s/j/a/v/p{name="p1"})$(s/j/a/v/q{name="p2"})$(s/j/a/v/r{name="p3"})$(s/j/a/v/s{name="p4"})$(s/j/b/v/p{name="p5"})$(s/j/b/v/q{name="p6"})$(s/j/b/v/r{name="p7"})$(s/j/b/v/s{name="p8"}) - $(s/k/a/v/p{name="p9"})$(s/k/a/v/q{name="p10"})$(s/k/a/v/r{name="p11"})$(s/k/a/v/s{name="p12"})$(s/k/b/v/p{name="p13"})$(s/k/b/v/q{name="p14"})$(s/k/b/v/r{name="p15"})$(s/k/b/v/s{name="p16"}) - $(s/l/a/v/p{name="p17"})$(s/l/a/v/q{name="p18"})$(s/l/a/v/r{name="p19"})$(s/l/a/v/s{name="p20"})$(s/l/b/v/p{name="p21"})$(s/l/b/v/q{name="p22"})$(s/l/b/v/r{name="p23"})$(s/l/b/v/s{name="p24"}) -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let theList1 = stateVariables["/list1"].activeChildren.map((x) => - me - .fromAst(stateVariables[x.componentName].stateValues.value) - .toString(), - ); - let theList2 = stateVariables["/list2"].activeChildren.map((x) => - me - .fromAst(stateVariables[x.componentName].stateValues.value) - .toString(), - ); - let theList3 = stateVariables["/list3"].activeChildren.map((x) => - me - .fromAst(stateVariables[x.componentName].stateValues.value) - .toString(), - ); - - expect(theList2).eqls(theList1); - expect(theList3).eqls(theList1); - - let theList4 = [...Array(24).keys()].map((i) => - me - .fromAst(stateVariables["/p" + (i + 1)].stateValues.value) - .toString(), - ); - - expect(theList4).eqls(theList1); - }); - }); - - it("select with hide will hide replacements but not copies", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

Selects and hide

-

,

-

$c, $d

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_p1")).should("have.text", "Selects and hide"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let c = await stateVariables["/c"].stateValues.value; - let d = await stateVariables["/d"].stateValues.value; - expect(["a", "b", "c", "d", "e"].includes(c)).eq(true); - expect(["a", "b", "c", "d", "e"].includes(d)).eq(true); - - cy.get(cesc(`#\\/_p2`)).should("have.text", `${c}, `); - cy.get(cesc(`#\\/_p3`)).should("have.text", `${c}, ${d}`); - }); - }); - - it("select with hide will hide named grandchildren replacements but not copies", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

Selects and hide

-

-

$a, , $c, , $e

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_p1")).should("have.text", "Selects and hide"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let a = stateVariables["/a"].stateValues.value; - let b = stateVariables["/b"].stateValues.value; - let c = stateVariables["/c"].stateValues.value; - let d = stateVariables["/d"].stateValues.value; - let e = stateVariables["/e"].stateValues.value; - expect(["a", "d"].includes(a)).eq(true); - expect(["b", "e"].includes(b)).eq(true); - expect(["c", "f"].includes(c)).eq(true); - expect(["a", "c", "e"].includes(d)).eq(true); - expect(["b", "d", "f"].includes(e)).eq(true); - - cy.get(cesc(`#\\/_p2`)).should("have.text", `${a}, ${b}, ${c}`); - cy.get(cesc(`#\\/_p3`)).should( - "have.text", - `${a}, , ${c}, ${d}, ${e}`, - ); - }); - }); - - it("selects hide dynamically", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - -

,

-

$c, $d

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let c = await stateVariables["/c"].stateValues.value; - let d = await stateVariables["/d"].stateValues.value; - expect(["a", "b", "c", "d", "e"].includes(c)).eq(true); - expect(["a", "b", "c", "d", "e"].includes(d)).eq(true); - - cy.get(cesc(`#\\/_p1`)).should("have.text", `${c}, `); - cy.get(cesc(`#\\/_p2`)).should("have.text", `${c}, ${d}`); - - cy.get(cesc("#\\/h1")).click(); - cy.get(cesc("#\\/h2")).click(); - - cy.get(cesc(`#\\/_p1`)).should("have.text", `, ${d}`); - cy.get(cesc(`#\\/_p2`)).should("have.text", `${c}, ${d}`); - - cy.get(cesc("#\\/h1")).click(); - cy.get(cesc("#\\/h2")).click(); - - cy.get(cesc(`#\\/_p1`)).should("have.text", `${c}, `); - cy.get(cesc(`#\\/_p2`)).should("have.text", `${c}, ${d}`); - }); - }); - - it("string and blank strings in options", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - foxjumps - elephanttrumpets - - -

a:

- -

a1: $a{assignNames="a11 a12 a13 a14"}

- -

pieces: -

q,r =

- - -

q2 = $q

-

r2 = $r

- - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let replacements = - stateVariables[ - stateVariables["/_select1"].replacements[0].componentName - ].replacements; - - let p1 = replacements[1].componentName; - let p2 = replacements[3].componentName; - let p3 = replacements[5].componentName; - - cy.get(cesc2("#" + p1)).should("have.text", `q,r = ab`); - cy.get(cesc2("#" + p2)).should("have.text", `q2 = a`); - cy.get(cesc2("#" + p3)).should("have.text", `r2 = b`); - }); - }); - - it("display error when miss a name in selectForVariants, inside text", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - -

We have a !

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_p1")).should("contain.text", "We have a "); - cy.get(cesc2("#/_p1")).should("contain.text", "!"); - cy.get(cesc2("#/_p1")).should( - "contain.text", - "Some variants are specified for select but no options are specified for possible variant name: banana", - ); - cy.get(cesc2("#/_p1")).should("contain.text", "lines 4–7"); - - cy.window().then(async (win) => { - let errorWarnings = await win.returnErrorWarnings1(); - - expect(errorWarnings.errors.length).eq(1); - expect(errorWarnings.warnings.length).eq(0); - - expect(errorWarnings.errors[0].message).contain( - "Some variants are specified for select but no options are specified for possible variant name: banana", - ); - expect(errorWarnings.errors[0].doenetMLrange.lineBegin).eq(4); - expect(errorWarnings.errors[0].doenetMLrange.charBegin).eq(24); - expect(errorWarnings.errors[0].doenetMLrange.lineEnd).eq(7); - expect(errorWarnings.errors[0].doenetMLrange.charEnd).eq(13); - }); - }); - - it("display error when repeat name in selectForVariants more times than numToSelect, inside p", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - -

We have a !

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_p1")).should("contain.text", "We have a "); - cy.get(cesc2("#/_p1")).should("contain.text", "!"); - cy.get(cesc2("#/_p1")).should( - "contain.text", - "Invalid variant name for select. Variant name apple appears in 2 options but number to select is 1", - ); - cy.get(cesc2("#/_p1")).should("contain.text", "lines 4–7"); - - cy.window().then(async (win) => { - let errorWarnings = await win.returnErrorWarnings1(); - - expect(errorWarnings.errors.length).eq(1); - expect(errorWarnings.warnings.length).eq(0); - - expect(errorWarnings.errors[0].message).contain( - "Invalid variant name for select. Variant name apple appears in 2 options but number to select is 1", - ); - expect(errorWarnings.errors[0].doenetMLrange.lineBegin).eq(4); - expect(errorWarnings.errors[0].doenetMLrange.charBegin).eq(18); - expect(errorWarnings.errors[0].doenetMLrange.lineEnd).eq(7); - expect(errorWarnings.errors[0].doenetMLrange.charEnd).eq(13); - }); - }); - - it("display error when repeat name in selectForVariants more times than numToSelect, inside document", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - We have a ! - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_document1")).should("contain.text", "We have a "); - cy.get(cesc2("#/_document1")).should("contain.text", "!"); - cy.get(cesc2("#/_document1")).should( - "contain.text", - "Variant name donut that is specified for select is not a possible variant name", - ); - cy.get(cesc2("#/_document1")).should("contain.text", "lines 4–8"); - - cy.window().then(async (win) => { - let errorWarnings = await win.returnErrorWarnings1(); - - expect(errorWarnings.errors.length).eq(1); - expect(errorWarnings.warnings.length).eq(0); - - expect(errorWarnings.errors[0].message).contain( - "Variant name donut that is specified for select is not a possible variant name", - ); - expect(errorWarnings.errors[0].doenetMLrange.lineBegin).eq(4); - expect(errorWarnings.errors[0].doenetMLrange.charBegin).eq(15); - expect(errorWarnings.errors[0].doenetMLrange.lineEnd).eq(8); - expect(errorWarnings.errors[0].doenetMLrange.charEnd).eq(13); - }); - }); - - it("display error when numToSelect is larger than number of options, inside graph", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

No points for graph!

- - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_p1")).should("contain.text", "No points for graph!"); - cy.get(cesc2("#/_document1")).should( - "contain.text", - "Cannot select 3 components from only 2", - ); - cy.get(cesc2("#/_document1")).should("contain.text", "lines 4–7"); - - cy.window().then(async (win) => { - let errorWarnings = await win.returnErrorWarnings1(); - - expect(errorWarnings.errors.length).eq(1); - expect(errorWarnings.warnings.length).eq(0); - - expect(errorWarnings.errors[0].message).contain( - "Cannot select 3 components from only 2", - ); - expect(errorWarnings.errors[0].doenetMLrange.lineBegin).eq(4); - expect(errorWarnings.errors[0].doenetMLrange.charBegin).eq(12); - expect(errorWarnings.errors[0].doenetMLrange.lineEnd).eq(7); - expect(errorWarnings.errors[0].doenetMLrange.charEnd).eq(13); - }); - }); - - it("numToSelect from selectfromsequence", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

n1 =

-

vars =

-

a1=$a1, b1=$b1, c1=$c1, d1=$d1, e1=$e1

- -

n2 =

-

vars =

-

a2=$a2, b2=$b2, c2=$c2, d2=$d2, e2=$e2

- -

n3 =

-

vars =

-

a3=$a3, b3=$b3, c3=$c3, d3=$d3, e3=$e3

- -

n4 =

-

vars =

-

a4=$a4, b4=$b4, c4=$c4, d4=$d4, e4=$e4

- -

n5 =

-

vars =

-

a5=$a5, b5=$b5, c5=$c5, d5=$d5, e5=$e5

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/n1"].stateValues.value; - let n2 = stateVariables["/n2"].stateValues.value; - let n3 = stateVariables["/n3"].stateValues.value; - let n4 = stateVariables["/n4"].stateValues.value; - let n5 = stateVariables["/n5"].stateValues.value; - - let vars1 = stateVariables["/vars1"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].stateValues.value, - ); - let vars2 = stateVariables["/vars2"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].stateValues.value, - ); - let vars3 = stateVariables["/vars3"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].stateValues.value, - ); - let vars4 = stateVariables["/vars4"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].stateValues.value, - ); - let vars5 = stateVariables["/vars5"].replacements.map( - (x) => - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].stateValues.value, - ); - - expect(vars1.length).eq(n1); - expect(vars2.length).eq(n2); - expect(vars3.length).eq(n3); - expect(vars4.length).eq(n4); - expect(vars5.length).eq(n5); - - vars1.length = 5; - vars2.length = 5; - vars3.length = 5; - vars4.length = 5; - vars5.length = 5; - - vars1.fill("", n1); - vars2.fill("", n2); - vars3.fill("", n3); - vars4.fill("", n4); - vars5.fill("", n5); - - let l = ["a", "b", "c", "d", "e"]; - - cy.get(cesc("#\\/p1")).should( - "have.text", - vars1.map((v, i) => `${l[i]}1=${v}`).join(", "), - ); - cy.get(cesc("#\\/p2")).should( - "have.text", - vars2.map((v, i) => `${l[i]}2=${v}`).join(", "), - ); - cy.get(cesc("#\\/p3")).should( - "have.text", - vars3.map((v, i) => `${l[i]}3=${v}`).join(", "), - ); - cy.get(cesc("#\\/p4")).should( - "have.text", - vars4.map((v, i) => `${l[i]}4=${v}`).join(", "), - ); - cy.get(cesc("#\\/p5")).should( - "have.text", - vars5.map((v, i) => `${l[i]}5=${v}`).join(", "), - ); - }); - }); - - it("add level to assign names even in shadow", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let q = stateVariables["/q"].stateValues.value; - - expect(stateVariables["/c/q"].stateValues.value).eq(q); - }); - }); - - it("ensure unique names", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let pNames1 = stateVariables["/_select1"].replacements.map( - (x) => - stateVariables[x.componentName].replacements[0] - .componentName, - ); - for (let pn of pNames1) { - cy.get(cesc2("#" + pn)).should("have.text", "What is this?"); - } - - let pNames2 = ["/A", "/B", "/C"].map( - (x) => stateVariables[x].replacements[0].componentName, - ); - for (let pn of pNames2) { - cy.get(cesc2("#" + pn)).should("have.text", "What is this?"); - } - - for (let pn of ["/D", "/E", "/F"]) { - cy.get(cesc2("#" + pn)).should("have.text", "What is this?"); - } - }); - }); }); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/selectfromsequence.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/selectfromsequence.cy.js index c5e57ef39..4d3323107 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/selectfromsequence.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/selectfromsequence.cy.js @@ -1,4 +1,3 @@ -import me from "math-expressions"; import { cesc, cesc2 } from "@doenet/utils"; describe("SelectFromSequence Tag Tests", function () { @@ -7,3827 +6,6 @@ describe("SelectFromSequence Tag Tests", function () { cy.visit("/"); }); - it("no parameters, select single number from 1 to 10", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 30; ind++) { - let num = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - expect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10].includes(num)).eq(true); - } - }); - }); - - it("select single number from 1 to 6", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 30; ind++) { - let num = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - expect([1, 2, 3, 4, 5, 6].includes(num)).eq(true); - } - }); - }); - - it("select single number from -3 to 5", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 30; ind++) { - let num = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - expect([-3, -2, -1, 0, 1, 2, 3, 4, 5].includes(num)).eq(true); - } - }); - }); - - it("select single number from -3 to 5, excluding 0", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 30; ind++) { - let num = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - expect([-3, -2, -1, 1, 2, 3, 4, 5].includes(num)).eq(true); - } - }); - }); - - it("select single odd number from -3 to 5", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 30; ind++) { - let num = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - expect([-3, -1, 1, 3, 5].includes(num)).eq(true); - } - }); - }); - - it("select single letter from c to h", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 30; ind++) { - let letter = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - expect(["c", "d", "e", "f", "g", "h"].includes(letter)).eq( - true, - ); - } - }); - }); - - it("select two even numbers from -4 to 4, excluding 0", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 - - - - - - - - - - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 20; ind++) { - let num1 = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - let num2 = - stateVariables[ - stateVariables["/sample" + ind].replacements[1] - .componentName - ].stateValues.value; - expect([-4, -2, 2, 4].includes(num1)).eq(true); - expect([-4, -2, 2, 4].includes(num2)).eq(true); - expect(num1).not.eq(num2); - } - }); - }); - - it("select two even numbers from -4 to 2, excluding 0 and combinations", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let allowedCombinations = [ - [-4, 2], - [-2, -4], - [2, -2], - ]; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 20; ind++) { - let num1 = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - let num2 = - stateVariables[ - stateVariables["/sample" + ind].replacements[1] - .componentName - ].stateValues.value; - - expect( - allowedCombinations.some( - (v) => v[0] === num1 && v[1] === num2, - ), - ).eq(true); - } - }); - }); - - it("select two even numbers from -4 to 2, excluding 0 and combinations, as copies", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -4 -2 - -2 - 2 - -4 - -4 -2 - -2 2 - 2 -4 - -

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let allowedCombinations = [ - [-4, 2], - [-2, -4], - [2, -2], - ]; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 20; ind++) { - let num1 = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - let num2 = - stateVariables[ - stateVariables["/sample" + ind].replacements[1] - .componentName - ].stateValues.value; - - expect( - allowedCombinations.some( - (v) => v[0] === num1 && v[1] === num2, - ), - ).eq(true); - } - }); - }); - - it("select two even numbers from -4 to 2, excluding 0 and combinations, exclude extras", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let allowedCombinations = [ - [-4, 2], - [-2, -4], - [2, -2], - ]; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 20; ind++) { - let num1 = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - let num2 = - stateVariables[ - stateVariables["/sample" + ind].replacements[1] - .componentName - ].stateValues.value; - - expect( - allowedCombinations.some( - (v) => v[0] === num1 && v[1] === num2, - ), - ).eq(true); - } - }); - }); - - it("select three numbers from 1 to 3, exclude combinations with two 1s", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let allowedCombinations = [ - [1, 2, 2], - [1, 2, 3], - [1, 3, 2], - [1, 3, 3], - [2, 1, 2], - [2, 1, 3], - [3, 1, 2], - [3, 1, 3], - [2, 2, 1], - [2, 3, 1], - [3, 2, 1], - [3, 3, 1], - [2, 2, 2], - [2, 2, 3], - [2, 3, 2], - [3, 2, 2], - [3, 3, 2], - [3, 2, 3], - [2, 3, 3], - [3, 3, 3], - ]; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 20; ind++) { - let num1 = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - let num2 = - stateVariables[ - stateVariables["/sample" + ind].replacements[1] - .componentName - ].stateValues.value; - let num3 = - stateVariables[ - stateVariables["/sample" + ind].replacements[2] - .componentName - ].stateValues.value; - - expect( - allowedCombinations.some( - (v) => v[0] === num1 && v[1] === num2 && v[2] === num3, - ), - ).eq(true); - } - }); - }); - - it("select three numbers from 1 to 3, exclude combinations with two 1s, duplicate excludes", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let allowedCombinations = [ - [1, 2, 2], - [1, 2, 3], - [1, 3, 2], - [1, 3, 3], - [2, 1, 2], - [2, 1, 3], - [3, 1, 2], - [3, 1, 3], - [2, 2, 1], - [2, 3, 1], - [3, 2, 1], - [3, 3, 1], - [2, 2, 2], - [2, 2, 3], - [2, 3, 2], - [3, 2, 2], - [3, 3, 2], - [3, 2, 3], - [2, 3, 3], - [3, 3, 3], - ]; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 20; ind++) { - let num1 = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - let num2 = - stateVariables[ - stateVariables["/sample" + ind].replacements[1] - .componentName - ].stateValues.value; - let num3 = - stateVariables[ - stateVariables["/sample" + ind].replacements[2] - .componentName - ].stateValues.value; - - expect( - allowedCombinations.some( - (v) => v[0] === num1 && v[1] === num2 && v[2] === num3, - ), - ).eq(true); - } - }); - }); - - it("select four numbers from 0 to 3, exclude positions of each number", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 20; ind++) { - let num1 = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - let num2 = - stateVariables[ - stateVariables["/sample" + ind].replacements[1] - .componentName - ].stateValues.value; - let num3 = - stateVariables[ - stateVariables["/sample" + ind].replacements[2] - .componentName - ].stateValues.value; - let num4 = - stateVariables[ - stateVariables["/sample" + ind].replacements[3] - .componentName - ].stateValues.value; - - expect([1, 2, 3].includes(num1)).eq(true); - expect([0, 2, 3].includes(num2)).eq(true); - expect([0, 1, 3].includes(num3)).eq(true); - expect([0, 1, 2].includes(num4)).eq(true); - } - }); - }); - - it("select three numbers from 1 to 3, without replacement exclude positions of each number", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 20; ind++) { - let num1 = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - let num2 = - stateVariables[ - stateVariables["/sample" + ind].replacements[1] - .componentName - ].stateValues.value; - let num3 = - stateVariables[ - stateVariables["/sample" + ind].replacements[2] - .componentName - ].stateValues.value; - - expect([2, 3].includes(num1)).eq(true); - expect([1, 3].includes(num2)).eq(true); - expect([1, 2].includes(num3)).eq(true); - } - }); - }); - - it("display error when select three numbers from 1 to 3, without replacement, exclude any place for 1", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_document1")).should( - "contain.text", - "Excluded over 70%", - ); - cy.get(cesc2("#/_document1")).should("contain.text", "line 2"); - - cy.window().then(async (win) => { - let errorWarnings = await win.returnErrorWarnings1(); - - expect(errorWarnings.errors.length).eq(1); - expect(errorWarnings.warnings.length).eq(0); - - expect(errorWarnings.errors[0].message).contain( - "Excluded over 70%", - ); - expect(errorWarnings.errors[0].doenetMLrange.lineBegin).eq(2); - expect(errorWarnings.errors[0].doenetMLrange.charBegin).eq(16); - expect(errorWarnings.errors[0].doenetMLrange.lineEnd).eq(2); - expect(errorWarnings.errors[0].doenetMLrange.charEnd).eq(130); - }); - }); - - it("select 10 numbers from 1 to 10, without replacement, exclude positions of each number", () => { - // make sure that exclude combinations does not enumerate all combinations excluded - // to count them - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

-

-

-

-

-

-

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let allNumbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 10; ind++) { - for (let j = 0; j < 10; j++) { - let num = - stateVariables[ - stateVariables["/sample" + ind].replacements[j] - .componentName - ].stateValues.value; - - let validNums = [...allNumbers]; - validNums.splice(j, 1); - - expect(validNums.includes(num)).eq(true); - } - } - }); - }); - - it("select five even numbers with replacement from -4 to 4, excluding 0", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 - - - - - - - - - - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 20; ind++) { - let num1 = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - let num2 = - stateVariables[ - stateVariables["/sample" + ind].replacements[1] - .componentName - ].stateValues.value; - let num3 = - stateVariables[ - stateVariables["/sample" + ind].replacements[2] - .componentName - ].stateValues.value; - let num4 = - stateVariables[ - stateVariables["/sample" + ind].replacements[3] - .componentName - ].stateValues.value; - let num5 = - stateVariables[ - stateVariables["/sample" + ind].replacements[4] - .componentName - ].stateValues.value; - expect([-4, -2, 2, 4].includes(num1)).eq(true); - expect([-4, -2, 2, 4].includes(num2)).eq(true); - expect([-4, -2, 2, 4].includes(num3)).eq(true); - expect([-4, -2, 2, 4].includes(num4)).eq(true); - expect([-4, -2, 2, 4].includes(num5)).eq(true); - } - }); - }); - - it("select five (number initially unresolved) even numbers with replacement from -4 to 4, excluding 0", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - - - - - - - - - - - - - - - $n3{name="n2"} - $num1{name="n"} - $n2+$num2+2 - $n3+$num3 - $num3{name="n3"} - 1 - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 20; ind++) { - let num1 = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - let num2 = - stateVariables[ - stateVariables["/sample" + ind].replacements[1] - .componentName - ].stateValues.value; - let num3 = - stateVariables[ - stateVariables["/sample" + ind].replacements[2] - .componentName - ].stateValues.value; - let num4 = - stateVariables[ - stateVariables["/sample" + ind].replacements[3] - .componentName - ].stateValues.value; - let num5 = - stateVariables[ - stateVariables["/sample" + ind].replacements[4] - .componentName - ].stateValues.value; - expect([-4, -2, 2, 4].includes(num1)).eq(true); - expect([-4, -2, 2, 4].includes(num2)).eq(true); - expect([-4, -2, 2, 4].includes(num3)).eq(true); - expect([-4, -2, 2, 4].includes(num4)).eq(true); - expect([-4, -2, 2, 4].includes(num5)).eq(true); - } - }); - }); - - it("asList", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let results = []; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - results.push(stateVariables["/u"].stateValues.value); - results.push(stateVariables["/v"].stateValues.value); - results.push(stateVariables["/w"].stateValues.value); - results.push(stateVariables["/x"].stateValues.value); - results.push(stateVariables["/y"].stateValues.value); - - for (let num of results) { - expect(num).gte(175).lte(205); - } - cy.get(cesc2("#/_p1")).should("have.text", results.join(", ")); - cy.get(cesc2("#/_p2")).should("have.text", results.join("")); - }); - }); - - it("copies don't resample", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 -

- - -

- -

- $sample1{name="noresample1"} - $sample2{name="noresample2"} - $noresample1{name="noreresample1"} - $noresample2{name="noreresample2"} -

- -

$_aslist1{name="noresamplelist"}

- -

$noresamplelist{name="noreresamplelist"}

- - $_p1{name="noresamplep"} - $noresamplep{name="noreresamplep"} - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let num1 = - stateVariables[ - stateVariables["/sample1"].replacements[0].componentName - ].stateValues.value; - let num2 = - stateVariables[ - stateVariables["/sample2"].replacements[0].componentName - ].stateValues.value; - expect(Number.isInteger(num1) && num1 >= 1 && num1 <= 100).eq(true); - expect(Number.isInteger(num2) && num2 >= 1 && num2 <= 100).eq(true); - expect( - stateVariables[ - stateVariables["/noresample1"].replacements[0].componentName - ].stateValues.value, - ).eq(num1); - expect( - stateVariables[ - stateVariables["/noresample2"].replacements[0].componentName - ].stateValues.value, - ).eq(num2); - expect( - stateVariables[ - stateVariables["/noreresample1"].replacements[0] - .componentName - ].stateValues.value, - ).eq(num1); - expect( - stateVariables[ - stateVariables["/noreresample2"].replacements[0] - .componentName - ].stateValues.value, - ).eq(num2); - - expect( - stateVariables[ - stateVariables["/noresamplelist"].activeChildren[0] - .componentName - ].stateValues.value, - ).eq(num1); - expect( - stateVariables[ - stateVariables["/noresamplelist"].activeChildren[1] - .componentName - ].stateValues.value, - ).eq(num2); - expect( - stateVariables[ - stateVariables["/noreresamplelist"].activeChildren[0] - .componentName - ].stateValues.value, - ).eq(num1); - expect( - stateVariables[ - stateVariables["/noreresamplelist"].activeChildren[1] - .componentName - ].stateValues.value, - ).eq(num2); - - expect( - stateVariables[ - stateVariables[ - stateVariables["/noresamplep"].activeChildren[0] - .componentName - ].activeChildren[0].componentName - ].stateValues.value, - ).eq(num1); - expect( - stateVariables[ - stateVariables[ - stateVariables["/noresamplep"].activeChildren[0] - .componentName - ].activeChildren[1].componentName - ].stateValues.value, - ).eq(num2); - expect( - stateVariables[ - stateVariables[ - stateVariables["/noreresamplep"].activeChildren[0] - .componentName - ].activeChildren[0].componentName - ].stateValues.value, - ).eq(num1); - expect( - stateVariables[ - stateVariables[ - stateVariables["/noreresamplep"].activeChildren[0] - .componentName - ].activeChildren[1].componentName - ].stateValues.value, - ).eq(num2); - }); - }); - - it("select doesn't change dynamically", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 - - -

- -

- - - -

- -

-

$maxnum2.value{assignNames="maxnum2a"}

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - let sample1numbers, sample2numbers; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let sample1replacements = stateVariables["/sample1"].replacements; - let sample2replacements = stateVariables["/sample2"].replacements; - expect(sample1replacements.length).eq(5); - expect(sample2replacements.length).eq(2); - sample1numbers = sample1replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - sample2numbers = sample2replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - - for (let num of sample1numbers) { - expect([1, 2, 3].includes(num)).eq(true); - } - for (let num of sample2numbers) { - expect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10].includes(num)).eq(true); - } - }); - - cy.log("Nothing changes when change mathinputs"); - cy.get(cesc("#\\/numToSelect") + " textarea").type( - `{end}{backspace}7{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/maxnum") + " textarea").type( - `{end}{backspace}11{enter}`, - { - force: true, - }, - ); - cy.get(cesc("#\\/numToSelect2") + " textarea").type( - `{end}{backspace}15{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/maxnum2") + " textarea").type( - `{end}{backspace}{backspace}18{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/maxnum2a")).should("contain.text", "18"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let sample1replacements = stateVariables["/sample1"].replacements; - let sample2replacements = stateVariables["/sample2"].replacements; - - expect( - sample1replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ), - ).eqls(sample1numbers); - expect( - sample2replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ), - ).eqls(sample2numbers); - }); - }); - - it("select doesn't resample in dynamic map", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - How many numbers do you want? -

- - - - - - -

- -

$_map1

-

$_aslist1

- - $p1{name="p4"} - $p2{name="p5"} - $p3{name="p6"} - - $p4{name="p7"} - $p5{name="p8"} - $p6{name="p9"} -

$_mathinput1.value{assignNames="m1"}

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let samplednumbers = []; - - cy.log("initially nothing"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - }); - - cy.log("sample one variable"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}1{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "1"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - samplednumbers.push(n1); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - for (let ind = 0; ind < 1; ind++) { - expect( - stateVariables[ - stateVariables[ - stateVariables["/p1"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p2"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p3"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p4"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p5"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p6"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p7"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p8"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p9"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - } - }); - - cy.log("go back to nothing"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}0{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "0"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - }); - - cy.log("get same number back"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}1{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "1"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - expect(n1).eq(samplednumbers[0]); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - - for (let ind = 0; ind < 1; ind++) { - expect( - stateVariables[ - stateVariables[ - stateVariables["/p1"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p2"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p3"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p4"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p5"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p6"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p7"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p8"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p9"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - } - }); - - cy.log("get two more samples"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}3{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "3"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - let n2 = stateVariables["/b/n"].stateValues.value; - let n3 = stateVariables["/c/n"].stateValues.value; - expect(n1).eq(samplednumbers[0]); - samplednumbers.push(n2); - samplednumbers.push(n3); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - for (let ind = 0; ind < 3; ind++) { - expect( - stateVariables[ - stateVariables[ - stateVariables["/p1"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p2"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p3"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p4"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p5"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p6"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p7"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p8"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p9"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - } - }); - - cy.log("go back to nothing"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}0{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "0"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - }); - - cy.log("get first two numbers back"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}2{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "2"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - let n2 = stateVariables["/b/n"].stateValues.value; - expect(n1).eq(samplednumbers[0]); - expect(n2).eq(samplednumbers[1]); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - - for (let ind = 0; ind < 2; ind++) { - expect( - stateVariables[ - stateVariables[ - stateVariables["/p1"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p2"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p3"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p4"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p5"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p6"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p7"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p8"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p9"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - } - }); - - cy.log("get six total samples"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}6{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "6"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - let n2 = stateVariables["/b/n"].stateValues.value; - let n3 = stateVariables["/c/n"].stateValues.value; - let n4 = stateVariables["/d/n"].stateValues.value; - let n5 = stateVariables["/e/n"].stateValues.value; - let n6 = stateVariables["/f/n"].stateValues.value; - expect(n1).eq(samplednumbers[0]); - expect(n2).eq(samplednumbers[1]); - expect(n3).eq(samplednumbers[2]); - samplednumbers.push(n4); - samplednumbers.push(n5); - samplednumbers.push(n6); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - for (let ind = 0; ind < 6; ind++) { - expect( - stateVariables[ - stateVariables[ - stateVariables["/p1"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p2"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p3"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p4"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p5"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p6"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p7"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p8"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p9"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - } - }); - - cy.log("go back to nothing"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}0{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "0"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - }); - - cy.log("get all six back"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}6{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "6"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - let n2 = stateVariables["/b/n"].stateValues.value; - let n3 = stateVariables["/c/n"].stateValues.value; - let n4 = stateVariables["/d/n"].stateValues.value; - let n5 = stateVariables["/e/n"].stateValues.value; - let n6 = stateVariables["/f/n"].stateValues.value; - expect(n1).eq(samplednumbers[0]); - expect(n2).eq(samplednumbers[1]); - expect(n3).eq(samplednumbers[2]); - expect(n4).eq(samplednumbers[3]); - expect(n5).eq(samplednumbers[4]); - expect(n6).eq(samplednumbers[5]); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - for (let ind = 0; ind < 6; ind++) { - expect( - stateVariables[ - stateVariables[ - stateVariables["/p1"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p2"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p3"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p4"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p5"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p6"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p7"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p8"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p9"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - } - }); - }); - - it("select single math, assign name", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

-

$u{name="u2"}

-

$v{name="v2"}

-

$w{name="w2"}

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let options = [ - me.fromText("x"), - me.fromText("x+y"), - me.fromText("x+2y"), - ]; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let u = stateVariables["/u"]; - let u2 = stateVariables["/u2"]; - let comparisons = options.map((el) => - el.equals(me.fromAst(u.stateValues.value)), - ); - expect(comparisons.includes(true)).eq(true); - expect(u.stateValues.value).eqls(u2.stateValues.value); - - let v = stateVariables["/v"]; - let v2 = stateVariables["/v2"]; - comparisons = options.map((el) => - el.equals(me.fromAst(v.stateValues.value)), - ); - expect(comparisons.includes(true)).eq(true); - expect(v.stateValues.value).eqls(v2.stateValues.value); - - let w = stateVariables["/w"]; - let w2 = stateVariables["/w2"]; - comparisons = options.map((el) => - el.equals(me.fromAst(w.stateValues.value)), - ); - expect(comparisons.includes(true)).eq(true); - expect(w.stateValues.value).eqls(w2.stateValues.value); - }); - }); - - it("select multiple maths, assign names", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 -

- -

-

$u{name="u2"}

-

$v{name="v2"}

-

$w{name="w2"}

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - let options = [ - me.fromText("x"), - me.fromText("x+y"), - me.fromText("x+2y"), - ]; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let u = stateVariables["/u"]; - let u2 = stateVariables["/u2"]; - let comparisons = options.map((el) => - el.equals(me.fromAst(u.stateValues.value)), - ); - expect(comparisons.includes(true)).eq(true); - expect(u.stateValues.value).eqls(u2.stateValues.value); - - let v = stateVariables["/v"]; - let v2 = stateVariables["/v2"]; - comparisons = options.map((el) => - el.equals(me.fromAst(v.stateValues.value)), - ); - expect(comparisons.includes(true)).eq(true); - expect(v.stateValues.value).eqls(v2.stateValues.value); - - let w = stateVariables["/w"]; - let w2 = stateVariables["/w2"]; - comparisons = options.map((el) => - el.equals(me.fromAst(w.stateValues.value)), - ); - expect(comparisons.includes(true)).eq(true); - expect(w.stateValues.value).eqls(w2.stateValues.value); - - let s = stateVariables["/s"]; - for (let ind = 3; ind < 6; ind++) { - let r = stateVariables[s.replacements[ind].componentName]; - comparisons = options.map((el) => - el.equals(me.fromAst(r.stateValues.value)), - ); - expect(comparisons.includes(true)).eq(true); - } - }); - }); - - it("select multiple maths, assign names, new namespace", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 -

- -

-

$(s/u{name="u2"})

-

$(s/v{name="v2"})

-

$(s/w{name="w2"})

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - let options = [ - me.fromText("x"), - me.fromText("x+y"), - me.fromText("x+2y"), - ]; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let u = stateVariables["/s/u"]; - let u2 = stateVariables["/u2"]; - let comparisons = options.map((el) => - el.equals(me.fromAst(u.stateValues.value)), - ); - expect(comparisons.includes(true)).eq(true); - expect(u.stateValues.value).eqls(u2.stateValues.value); - - let v = stateVariables["/s/v"]; - let v2 = stateVariables["/v2"]; - comparisons = options.map((el) => - el.equals(me.fromAst(v.stateValues.value)), - ); - expect(comparisons.includes(true)).eq(true); - expect(v.stateValues.value).eqls(v2.stateValues.value); - - let w = stateVariables["/s/w"]; - let w2 = stateVariables["/w2"]; - comparisons = options.map((el) => - el.equals(me.fromAst(w.stateValues.value)), - ); - expect(comparisons.includes(true)).eq(true); - expect(w.stateValues.value).eqls(w2.stateValues.value); - - let s = stateVariables["/s"]; - for (let ind = 3; ind < 6; ind++) { - let r = stateVariables[s.replacements[ind].componentName]; - comparisons = options.map((el) => - el.equals(me.fromAst(r.stateValues.value)), - ); - expect(comparisons.includes(true)).eq(true); - } - }); - }); - - it("selectfromsequence with hide will hide replacements", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

Selectfromsequences and hide

-

,

-

$c,

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_p1")).should( - "have.text", - "Selectfromsequences and hide", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let c = await stateVariables["/c"].stateValues.value; - let d = await stateVariables["/d"].stateValues.value; - expect(["a", "b", "c", "d", "e"].includes(c)).eq(true); - expect(["a", "b", "c", "d", "e"].includes(d)).eq(true); - - cy.get(cesc(`#\\/_p2`)).should("have.text", `${c}, `); - cy.get(cesc(`#\\/_p3`)).should("have.text", `${c}, ${d}`); - }); - }); - - it("select multiple numbers with excludecombinations, adjust for round-off error", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let allowedCombinations = [ - [0.1, 0.2], - [0.2, 0.1], - [0.3, 0.2], - ]; - let foundCombination = [false, false, false]; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 20; ind++) { - let x1 = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - let x2 = - stateVariables[ - stateVariables["/sample" + ind].replacements[1] - .componentName - ].stateValues.value; - - let combination = -1; - for (let [ind, comb] of allowedCombinations.entries()) { - if ( - Math.abs(comb[0] - x1) < 1e-14 && - Math.abs(comb[1] - x2) < 1e-14 - ) { - combination = ind; - } - } - - expect(combination).not.eq(-1); - - foundCombination[combination] = true; - } - - for (let i = 0; i < 3; i++) { - expect(foundCombination[i]).be.true; - } - }); - }); - - it("select multiple math with excludecombinations, adjust for round-off error", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let allowedCombinations = [ - [0.1, 0.2], - [0.2, 0.1], - [0.3, 0.2], - ]; - let foundCombination = [false, false, false]; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 20; ind++) { - let x1 = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - let x2 = - stateVariables[ - stateVariables["/sample" + ind].replacements[1] - .componentName - ].stateValues.value; - - let combination = -1; - for (let [ind, comb] of allowedCombinations.entries()) { - if ( - Math.abs(comb[0] - x1) < 1e-14 && - Math.abs(comb[1] - x2) < 1e-14 - ) { - combination = ind; - } - } - - expect(combination).not.eq(-1); - - foundCombination[combination] = true; - } - - for (let i = 0; i < 3; i++) { - expect(foundCombination[i]).be.true; - } - }); - }); - - it("select multiple maths with excludes and excludecombinations", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let allowedCombinations = [ - [me.fromText("x"), me.fromText("x+3y")], - [me.fromText("x+y"), me.fromText("x")], - [me.fromText("x+3y"), me.fromText("x+y")], - ]; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 20; ind++) { - let x1 = me.fromAst( - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value, - ); - let x2 = me.fromAst( - stateVariables[ - stateVariables["/sample" + ind].replacements[1] - .componentName - ].stateValues.value, - ); - - expect( - allowedCombinations.some( - (v) => v[0].equals(x1) && v[1].equals(x2), - ), - ).eq(true); - } - }); - }); - - it("select multiple maths with excludes and excludecombinations, as copies", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x x+y - x+y - x+3y - x - x x+y - x+y x+3y - -

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let allowedCombinations = [ - [me.fromText("x"), me.fromText("x+3y")], - [me.fromText("x+y"), me.fromText("x")], - [me.fromText("x+3y"), me.fromText("x+y")], - ]; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 20; ind++) { - let x1 = me.fromAst( - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value, - ); - let x2 = me.fromAst( - stateVariables[ - stateVariables["/sample" + ind].replacements[1] - .componentName - ].stateValues.value, - ); - - expect( - allowedCombinations.some( - (v) => v[0].equals(x1) && v[1].equals(x2), - ), - ).eq(true); - } - }); - }); - - it("select multiple maths with excludes and excludecombinations, exclude extras", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let allowedCombinations = [ - [me.fromText("x"), me.fromText("x+3y")], - [me.fromText("x+y"), me.fromText("x")], - [me.fromText("x+3y"), me.fromText("x+y")], - ]; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 20; ind++) { - let x1 = me.fromAst( - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value, - ); - let x2 = me.fromAst( - stateVariables[ - stateVariables["/sample" + ind].replacements[1] - .componentName - ].stateValues.value, - ); - - expect( - allowedCombinations.some( - (v) => v[0].equals(x1) && v[1].equals(x2), - ), - ).eq(true); - } - }); - }); - - it("select multiple letters with excludes and excludecombinations", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let allowedCombinations = [ - ["m", "s"], - ["s", "v"], - ["v", "m"], - ]; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 20; ind++) { - let x1 = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - let x2 = - stateVariables[ - stateVariables["/sample" + ind].replacements[1] - .componentName - ].stateValues.value; - - expect( - allowedCombinations.some((v) => v[0] === x1 && v[1] === x2), - ).eq(true); - } - }); - }); - - it("select multiple letters with excludes and excludecombinations, as copies", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - m v - s - v - s - m v - s m - -

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let allowedCombinations = [ - ["m", "s"], - ["s", "v"], - ["v", "m"], - ]; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 20; ind++) { - let x1 = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - let x2 = - stateVariables[ - stateVariables["/sample" + ind].replacements[1] - .componentName - ].stateValues.value; - - expect( - allowedCombinations.some((v) => v[0] === x1 && v[1] === x2), - ).eq(true); - } - }); - }); - - it("select multiple letters with excludes and excludecombinations, exclude extras", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let allowedCombinations = [ - ["m", "s"], - ["s", "v"], - ["v", "m"], - ]; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 20; ind++) { - let x1 = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - let x2 = - stateVariables[ - stateVariables["/sample" + ind].replacements[1] - .componentName - ].stateValues.value; - - expect( - allowedCombinations.some((v) => v[0] === x1 && v[1] === x2), - ).eq(true); - } - }); - }); - - it("select numbers and sort", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- -

$_aslist1{name="aslist2"}

- $_p1{name="p3"} - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let lastnumber = -20; - let originalnumbers = stateVariables[ - "/_selectfromsequence1" - ].replacements.map((x) => stateVariables[x.componentName]); - let secondnumbers = stateVariables["/aslist2"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - let thirdnumbers = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map((x) => stateVariables[x.componentName]); - for (let i = 0; i < 20; i++) { - let newnumber = originalnumbers[i].stateValues.value; - expect(newnumber).gte(lastnumber); - lastnumber = newnumber; - expect(secondnumbers[i].stateValues.value).eq(newnumber); - expect(thirdnumbers[i].stateValues.value).eq(newnumber); - } - }); - }); - - it("select letters and sort", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- -

$_aslist1{name="aslist2"}

- $_p1{name="p3"} - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let lastletter = "a"; - let originalletters = stateVariables[ - "/_selectfromsequence1" - ].replacements.map((x) => stateVariables[x.componentName]); - let secondletters = stateVariables["/aslist2"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - let thirdletters = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map((x) => stateVariables[x.componentName]); - for (let i = 0; i < 20; i++) { - let newletter = originalletters[i].stateValues.value; - expect(newletter.length).gte(lastletter.length); - expect( - newletter.length > lastletter.length || - newletter >= lastletter, - ).to.be.true; - lastletter = newletter; - expect(secondletters[i].stateValues.value).eq(newletter); - expect(thirdletters[i].stateValues.value).eq(newletter); - } - }); - }); - - it("selectfromsequence hides dynamically", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - -

,

-

$c, $d

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let c = await stateVariables["/c"].stateValues.value; - let d = await stateVariables["/d"].stateValues.value; - expect(["a", "b", "c", "d", "e"].includes(c)).eq(true); - expect(["a", "b", "c", "d", "e"].includes(d)).eq(true); - - cy.get(cesc(`#\\/_p1`)).should("have.text", `${c}, `); - cy.get(cesc(`#\\/_p2`)).should("have.text", `${c}, ${d}`); - - cy.get(cesc("#\\/h1")).click(); - cy.get(cesc("#\\/h2")).click(); - - cy.get(cesc(`#\\/_p1`)).should("have.text", `, ${d}`); - cy.get(cesc(`#\\/_p2`)).should("have.text", `${c}, ${d}`); - - cy.get(cesc("#\\/h1")).click(); - cy.get(cesc("#\\/h2")).click(); - - cy.get(cesc(`#\\/_p1`)).should("have.text", `${c}, `); - cy.get(cesc(`#\\/_p2`)).should("have.text", `${c}, ${d}`); - }); - }); - - it("selectfromsequence defaults to fixed", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - -

- - - -

-

- $a{name="a2"} - $b{name="b2"} - $c{name="c2"} -

-

- - - -

-

- - - -

-

- $a.fixed{assignNames="af"} - $b.fixed{assignNames="bf"} - $c.fixed{assignNames="cf"} -

-

- $a2.fixed{assignNames="a2f"} - $b2.fixed{assignNames="b2f"} - $c2.fixed{assignNames="c2f"} -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let a = stateVariables["/a"].stateValues.value; - let b = stateVariables["/b"].stateValues.value; - let c = stateVariables["/c"].stateValues.value; - expect(["a", "b", "c", "d", "e"].includes(a)).eq(true); - expect(["a", "b", "c", "d", "e"].includes(b)).eq(true); - expect(["a", "b", "c", "d", "e"].includes(c)).eq(true); - - cy.get(cesc("#\\/a")).should("have.text", a); - cy.get(cesc("#\\/b")).should("have.text", b); - cy.get(cesc("#\\/c")).should("have.text", c); - cy.get(cesc("#\\/a2")).should("have.text", a); - cy.get(cesc("#\\/b2")).should("have.text", b); - cy.get(cesc("#\\/c2")).should("have.text", c); - - cy.get(cesc("#\\/af")).should("have.text", "true"); - cy.get(cesc("#\\/bf")).should("have.text", "false"); - cy.get(cesc("#\\/cf")).should("have.text", "true"); - cy.get(cesc("#\\/a2f")).should("have.text", "true"); - cy.get(cesc("#\\/b2f")).should("have.text", "false"); - cy.get(cesc("#\\/c2f")).should("have.text", "true"); - - cy.get(cesc("#\\/a3_input")).clear().type("f{enter}"); - cy.get(cesc("#\\/b3_input")).clear().type("g{enter}"); - cy.get(cesc("#\\/c3_input")).clear().type("h{enter}"); - - cy.get(cesc("#\\/a")).should("have.text", a); - cy.get(cesc("#\\/b")).should("have.text", "g"); - cy.get(cesc("#\\/c")).should("have.text", c); - cy.get(cesc("#\\/a2")).should("have.text", a); - cy.get(cesc("#\\/b2")).should("have.text", "g"); - cy.get(cesc("#\\/c2")).should("have.text", c); - - cy.get(cesc("#\\/a4_input")).clear().type("i{enter}"); - cy.get(cesc("#\\/b4_input")).clear().type("j{enter}"); - cy.get(cesc("#\\/c4_input")).clear().type("k{enter}"); - - cy.get(cesc("#\\/a")).should("have.text", a); - cy.get(cesc("#\\/b")).should("have.text", "j"); - cy.get(cesc("#\\/c")).should("have.text", c); - cy.get(cesc("#\\/a2")).should("have.text", a); - cy.get(cesc("#\\/b2")).should("have.text", "j"); - cy.get(cesc("#\\/c2")).should("have.text", c); - - cy.get(cesc("#\\/f1")).click(); - cy.get(cesc("#\\/f2")).click(); - - cy.get(cesc("#\\/af")).should("have.text", "true"); - cy.get(cesc("#\\/bf")).should("have.text", "true"); - cy.get(cesc("#\\/cf")).should("have.text", "false"); - cy.get(cesc("#\\/a2f")).should("have.text", "true"); - cy.get(cesc("#\\/b2f")).should("have.text", "true"); - cy.get(cesc("#\\/c2f")).should("have.text", "false"); - - cy.get(cesc("#\\/a3_input")).clear().type("l{enter}"); - cy.get(cesc("#\\/b3_input")).clear().type("m{enter}"); - cy.get(cesc("#\\/c3_input")).clear().type("n{enter}"); - - cy.get(cesc("#\\/a")).should("have.text", a); - cy.get(cesc("#\\/b")).should("have.text", "j"); - cy.get(cesc("#\\/c")).should("have.text", "n"); - cy.get(cesc("#\\/a2")).should("have.text", a); - cy.get(cesc("#\\/b2")).should("have.text", "j"); - cy.get(cesc("#\\/c2")).should("have.text", "n"); - - cy.get(cesc("#\\/a4_input")).clear().type("o{enter}"); - cy.get(cesc("#\\/b4_input")).clear().type("p{enter}"); - cy.get(cesc("#\\/c4_input")).clear().type("q{enter}"); - - cy.get(cesc("#\\/a")).should("have.text", a); - cy.get(cesc("#\\/b")).should("have.text", "j"); - cy.get(cesc("#\\/c")).should("have.text", "q"); - cy.get(cesc("#\\/a2")).should("have.text", a); - cy.get(cesc("#\\/b2")).should("have.text", "j"); - cy.get(cesc("#\\/c2")).should("have.text", "q"); - }); - }); - - it("numToSelect from selectfromsequence", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

n1 =

-

nums =

-

a1=$a1, b1=$b1, c1=$c1, d1=$d1, e1=$e1

- -

n2 =

-

nums =

-

a2=$a2, b2=$b2, c2=$c2, d2=$d2, e2=$e2

- -

n3 =

-

nums =

-

a3=$a3, b3=$b3, c3=$c3, d3=$d3, e3=$e3

- -

n4 =

-

nums =

-

a4=$a4, b4=$b4, c4=$c4, d4=$d4, e4=$e4

- -

n5 =

-

nums =

-

a5=$a5, b5=$b5, c5=$c5, d5=$d5, e5=$e5

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/n1"].stateValues.value; - let n2 = stateVariables["/n2"].stateValues.value; - let n3 = stateVariables["/n3"].stateValues.value; - let n4 = stateVariables["/n4"].stateValues.value; - let n5 = stateVariables["/n5"].stateValues.value; - - let nums1 = stateVariables["/nums1"].replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let nums2 = stateVariables["/nums2"].replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let nums3 = stateVariables["/nums3"].replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let nums4 = stateVariables["/nums4"].replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let nums5 = stateVariables["/nums5"].replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - - expect(nums1.length).eq(n1); - expect(nums2.length).eq(n2); - expect(nums3.length).eq(n3); - expect(nums4.length).eq(n4); - expect(nums5.length).eq(n5); - - nums1.length = 5; - nums2.length = 5; - nums3.length = 5; - nums4.length = 5; - nums5.length = 5; - - nums1.fill("", n1); - nums2.fill("", n2); - nums3.fill("", n3); - nums4.fill("", n4); - nums5.fill("", n5); - - let l = ["a", "b", "c", "d", "e"]; - - cy.get(cesc("#\\/p1")).should( - "have.text", - nums1.map((v, i) => `${l[i]}1=${v}`).join(", "), - ); - cy.get(cesc("#\\/p2")).should( - "have.text", - nums2.map((v, i) => `${l[i]}2=${v}`).join(", "), - ); - cy.get(cesc("#\\/p3")).should( - "have.text", - nums3.map((v, i) => `${l[i]}3=${v}`).join(", "), - ); - cy.get(cesc("#\\/p4")).should( - "have.text", - nums4.map((v, i) => `${l[i]}4=${v}`).join(", "), - ); - cy.get(cesc("#\\/p5")).should( - "have.text", - nums5.map((v, i) => `${l[i]}5=${v}`).join(", "), - ); - }); - }); - - it("rounding", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

-

- -

$n1

-

$n2

-

$n3

-

$n4

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let n1 = stateVariables["/n1"].stateValues.value; - let n2 = stateVariables["/n2"].stateValues.value; - let n3 = stateVariables["/n3"].stateValues.value; - let n4 = stateVariables["/n4"].stateValues.value; - - cy.get(cesc("#\\/n1")).should( - "have.text", - String(Math.round(n1 * 10 ** 8) / 10 ** 8), - ); - cy.get(cesc("#\\/n2")).should( - "have.text", - String(Math.round(n2 * 10 ** 1) / 10 ** 1), - ); - cy.get(cesc("#\\/n3")).should( - "have.text", - String(Math.round(n3 * 10 ** 3) / 10 ** 3), - ); - cy.get(cesc("#\\/n4")).should("have.text", String(n4) + ".0"); - - cy.get(cesc("#\\/n1a")).should( - "have.text", - String(Math.round(n1 * 10 ** 8) / 10 ** 8), - ); - cy.get(cesc("#\\/n2a")).should( - "have.text", - String(Math.round(n2 * 10 ** 1) / 10 ** 1), - ); - cy.get(cesc("#\\/n3a")).should( - "have.text", - String(Math.round(n3 * 10 ** 3) / 10 ** 3), - ); - cy.get(cesc("#\\/n4a")).should("have.text", String(n4) + ".0"); - }); - }); - - it("display error when select 3 from 1, inside text", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_document1")).should( - "contain.text", - "Cannot select 3 values from a sequence of length 1", - ); - cy.get(cesc2("#/_document1")).should("contain.text", "line 2"); - - cy.window().then(async (win) => { - let errorWarnings = await win.returnErrorWarnings1(); - - expect(errorWarnings.errors.length).eq(1); - expect(errorWarnings.warnings.length).eq(0); - - expect(errorWarnings.errors[0].message).contain( - "Cannot select 3 values from a sequence of length 1", - ); - expect(errorWarnings.errors[0].doenetMLrange.lineBegin).eq(2); - expect(errorWarnings.errors[0].doenetMLrange.charBegin).eq(17); - expect(errorWarnings.errors[0].doenetMLrange.lineEnd).eq(2); - expect(errorWarnings.errors[0].doenetMLrange.charEnd).eq(65); - }); - }); - - it("check bugfix for non-constant exclude and unique variants", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - a -

Number to exclude: 2

-

- -

$n

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let n = stateVariables["/n"].stateValues.value; - - cy.get(cesc("#\\/n")).should("have.text", String(n)); - - cy.get(cesc("#\\/na")).should("have.text", String(n)); - - expect(n === 1 || n === 3).eq(true); - }); - }); - - it("check bugfix for non-constant exclude and defaulting to unique variants", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Number to exclude: 2

-

- -

$n

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let n = stateVariables["/n"].stateValues.value; - - cy.get(cesc("#\\/n")).should("have.text", String(n)); - - cy.get(cesc("#\\/na")).should("have.text", String(n)); - - expect(n === 1 || n === 3).eq(true); - }); - }); - it("selectfromsequence depending on selectfromsequence handles reload", () => { cy.get("#testRunner_toggleControls").click(); cy.get("#testRunner_allowLocalState").click(); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/selectprimenumbers.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/selectprimenumbers.cy.js deleted file mode 100644 index 457f14338..000000000 --- a/packages/test-cypress/cypress/e2e/tagSpecific/selectprimenumbers.cy.js +++ /dev/null @@ -1,2695 +0,0 @@ -import { cesc, cesc2 } from "@doenet/utils"; - -describe("SelecPrimeNumbers Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("no parameters, select single prime number from 2 to 100", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 30; ind++) { - let num = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - expect( - [ - 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, - 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, - ].includes(num), - ).eq(true); - } - }); - }); - - it("select single prime number from 2 to 6", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 30; ind++) { - let num = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - expect([2, 3, 5].includes(num)).eq(true); - } - }); - }); - - it("select single prime number from 9 to 39", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 30; ind++) { - let num = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - expect([11, 13, 17, 19, 23, 29, 31, 37].includes(num)).eq(true); - } - }); - }); - - it("select single prime number from 9 to 39, excluding 19", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 30; ind++) { - let num = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - expect([11, 13, 17, 23, 29, 31, 37].includes(num)).eq(true); - } - }); - }); - - it("select two prime numbers from 1020 to 1050, excluding 1031 and 1049", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 - - - - - - - - - - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 20; ind++) { - let num1 = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - let num2 = - stateVariables[ - stateVariables["/sample" + ind].replacements[1] - .componentName - ].stateValues.value; - expect([1021, 1033, 1039, 1051].includes(num1)).eq(true); - expect([1021, 1033, 1039, 1051].includes(num2)).eq(true); - expect(num1).not.eq(num2); - } - }); - }); - - it("select two prime numbers from 1020 to 1050, excluding 1031 and 1049 and combinations", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let allowedCombinations = [ - [1021, 1039], - [1033, 1021], - [1039, 1033], - ]; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 20; ind++) { - let num1 = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - let num2 = - stateVariables[ - stateVariables["/sample" + ind].replacements[1] - .componentName - ].stateValues.value; - - expect( - allowedCombinations.some( - (v) => v[0] === num1 && v[1] === num2, - ), - ).eq(true); - } - }); - }); - - it("select two prime numbers from 1020 to 1050, excluding 1031 and 1049 and combinations, as copies", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 1021 1033 - 1033 - 1039 - 1021 - 1021 1033 - 1033 1039 - 1039 1021 - -

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let allowedCombinations = [ - [1021, 1039], - [1033, 1021], - [1039, 1033], - ]; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 20; ind++) { - let num1 = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - let num2 = - stateVariables[ - stateVariables["/sample" + ind].replacements[1] - .componentName - ].stateValues.value; - - expect( - allowedCombinations.some( - (v) => v[0] === num1 && v[1] === num2, - ), - ).eq(true); - } - }); - }); - - it("select two prime numbers from 1020 to 1050, excluding 1031 and 1049 and combinations, exclude extras", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let allowedCombinations = [ - [1021, 1039], - [1033, 1021], - [1039, 1033], - ]; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 20; ind++) { - let num1 = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - let num2 = - stateVariables[ - stateVariables["/sample" + ind].replacements[1] - .componentName - ].stateValues.value; - - expect( - allowedCombinations.some( - (v) => v[0] === num1 && v[1] === num2, - ), - ).eq(true); - } - }); - }); - - it("select three prime numbers up to 5, exclude combinations with two 2s", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let allowedCombinations = [ - [2, 3, 3], - [2, 3, 5], - [2, 5, 3], - [2, 5, 5], - [3, 2, 3], - [3, 2, 5], - [5, 2, 3], - [5, 2, 5], - [3, 3, 2], - [3, 5, 2], - [5, 3, 2], - [5, 5, 2], - [3, 3, 3], - [3, 3, 5], - [3, 5, 3], - [5, 3, 3], - [5, 5, 3], - [5, 3, 5], - [3, 5, 5], - [5, 5, 5], - ]; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 20; ind++) { - let num1 = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - let num2 = - stateVariables[ - stateVariables["/sample" + ind].replacements[1] - .componentName - ].stateValues.value; - let num3 = - stateVariables[ - stateVariables["/sample" + ind].replacements[2] - .componentName - ].stateValues.value; - - expect( - allowedCombinations.some( - (v) => v[0] === num1 && v[1] === num2 && v[2] === num3, - ), - ).eq(true); - } - }); - }); - - it("select three prime numbers up to 5, exclude combinations with two 2s, duplicate excludes", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let allowedCombinations = [ - [2, 3, 3], - [2, 3, 5], - [2, 5, 3], - [2, 5, 5], - [3, 2, 3], - [3, 2, 5], - [5, 2, 3], - [5, 2, 5], - [3, 3, 2], - [3, 5, 2], - [5, 3, 2], - [5, 5, 2], - [3, 3, 3], - [3, 3, 5], - [3, 5, 3], - [5, 3, 3], - [5, 5, 3], - [5, 3, 5], - [3, 5, 5], - [5, 5, 5], - ]; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 20; ind++) { - let num1 = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - let num2 = - stateVariables[ - stateVariables["/sample" + ind].replacements[1] - .componentName - ].stateValues.value; - let num3 = - stateVariables[ - stateVariables["/sample" + ind].replacements[2] - .componentName - ].stateValues.value; - - expect( - allowedCombinations.some( - (v) => v[0] === num1 && v[1] === num2 && v[2] === num3, - ), - ).eq(true); - } - }); - }); - - it("select four prime numbers from 3 to 11, exclude positions of each number", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 20; ind++) { - let num1 = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - let num2 = - stateVariables[ - stateVariables["/sample" + ind].replacements[1] - .componentName - ].stateValues.value; - let num3 = - stateVariables[ - stateVariables["/sample" + ind].replacements[2] - .componentName - ].stateValues.value; - let num4 = - stateVariables[ - stateVariables["/sample" + ind].replacements[3] - .componentName - ].stateValues.value; - - expect([5, 7, 11].includes(num1)).eq(true); - expect([3, 7, 11].includes(num2)).eq(true); - expect([3, 5, 11].includes(num3)).eq(true); - expect([3, 5, 7].includes(num4)).eq(true); - } - }); - }); - - it("select three prime numbers up to 5, without replacement exclude positions of each number", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 20; ind++) { - let num1 = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - let num2 = - stateVariables[ - stateVariables["/sample" + ind].replacements[1] - .componentName - ].stateValues.value; - let num3 = - stateVariables[ - stateVariables["/sample" + ind].replacements[2] - .componentName - ].stateValues.value; - - expect([3, 5].includes(num1)).eq(true); - expect([2, 5].includes(num2)).eq(true); - expect([2, 3].includes(num3)).eq(true); - } - }); - }); - - it("select three prime numbers up to 5, without replacement, exclude any place for 2", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

- `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_document1")).should( - "contain.text", - "Excluded over 70%", - ); - cy.get(cesc2("#/_document1")).should("contain.text", "line 2"); - - cy.window().then(async (win) => { - let errorWarnings = await win.returnErrorWarnings1(); - - expect(errorWarnings.errors.length).eq(1); - expect(errorWarnings.warnings.length).eq(0); - - expect(errorWarnings.errors[0].message).contain( - "Excluded over 70%", - ); - expect(errorWarnings.errors[0].doenetMLrange.lineBegin).eq(2); - expect(errorWarnings.errors[0].doenetMLrange.charBegin).eq(16); - expect(errorWarnings.errors[0].doenetMLrange.lineEnd).eq(2); - expect(errorWarnings.errors[0].doenetMLrange.charEnd).eq(127); - }); - }); - - it("select 10 prime numbers from the first 10, without replacement, exclude positions of each number", () => { - // make sure that exclude combinations does not enumerate all combinations excluded - // to count them - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

-

-

-

-

-

-

-

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let allNumbers = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]; - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 10; ind++) { - for (let j = 0; j < 10; j++) { - let num = - stateVariables[ - stateVariables["/sample" + ind].replacements[j] - .componentName - ].stateValues.value; - - let validNums = [...allNumbers]; - validNums.splice(j, 1); - - expect(validNums.includes(num)).eq(true); - } - } - }); - }); - - it("select two prime numbers with replacement from 1020 to 1050, excluding 1031 and 1049", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 - - - - - - - - - - - - - - - - - - - - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 20; ind++) { - let num1 = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - let num2 = - stateVariables[ - stateVariables["/sample" + ind].replacements[1] - .componentName - ].stateValues.value; - let num3 = - stateVariables[ - stateVariables["/sample" + ind].replacements[2] - .componentName - ].stateValues.value; - let num4 = - stateVariables[ - stateVariables["/sample" + ind].replacements[3] - .componentName - ].stateValues.value; - let num5 = - stateVariables[ - stateVariables["/sample" + ind].replacements[4] - .componentName - ].stateValues.value; - expect([1021, 1033, 1039, 1051].includes(num1)).eq(true); - expect([1021, 1033, 1039, 1051].includes(num2)).eq(true); - expect([1021, 1033, 1039, 1051].includes(num3)).eq(true); - expect([1021, 1033, 1039, 1051].includes(num4)).eq(true); - expect([1021, 1033, 1039, 1051].includes(num5)).eq(true); - } - }); - }); - - it("select five (number initially unresolved) prime numbers with replacement from 1020 to 1050, excluding 1031 and 1049", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - - - - - - - - - - - - - - - $n3{name="n2"} - $num1{name="n"} - $n2+$num2+2 - $n3+$num3 - $num3{name="n3"} - 1 - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 1; ind <= 20; ind++) { - let num1 = - stateVariables[ - stateVariables["/sample" + ind].replacements[0] - .componentName - ].stateValues.value; - let num2 = - stateVariables[ - stateVariables["/sample" + ind].replacements[1] - .componentName - ].stateValues.value; - let num3 = - stateVariables[ - stateVariables["/sample" + ind].replacements[2] - .componentName - ].stateValues.value; - let num4 = - stateVariables[ - stateVariables["/sample" + ind].replacements[3] - .componentName - ].stateValues.value; - let num5 = - stateVariables[ - stateVariables["/sample" + ind].replacements[4] - .componentName - ].stateValues.value; - expect([1021, 1033, 1039, 1051].includes(num1)).eq(true); - expect([1021, 1033, 1039, 1051].includes(num2)).eq(true); - expect([1021, 1033, 1039, 1051].includes(num3)).eq(true); - expect([1021, 1033, 1039, 1051].includes(num4)).eq(true); - expect([1021, 1033, 1039, 1051].includes(num5)).eq(true); - } - }); - }); - - it("select 100 large prime numbers, check that are prime", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 - - - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - for (let ind = 0; ind < 100; ind++) { - let num = - stateVariables[ - stateVariables["/sample"].replacements[ind] - .componentName - ].stateValues.value; - - expect(Number.isInteger(num) && num >= 2 && num <= 1000000).eq( - true, - ); - - let isprime = true; - let sqrtnum = Math.sqrt(num); - for (let i = 2; i <= sqrtnum; i++) { - if (num % i === 0) { - isprime = false; - break; - } - } - expect(isprime).eq(true); - } - }); - }); - - it("asList", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let results = []; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - results.push(stateVariables["/u"].stateValues.value); - results.push(stateVariables["/v"].stateValues.value); - results.push(stateVariables["/w"].stateValues.value); - results.push(stateVariables["/x"].stateValues.value); - results.push(stateVariables["/y"].stateValues.value); - - for (let num of results) { - expect([179, 181, 191, 193, 197, 199].includes(num)); - } - cy.get(cesc2("#/_p1")).should("have.text", results.join(", ")); - cy.get(cesc2("#/_p2")).should("have.text", results.join("")); - }); - }); - - it("copies don't resample", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 -

- - -

- -

- $sample1{name="noresample1"} - $sample2{name="noresample2"} - $noresample1{name="noreresample1"} - $noresample2{name="noreresample2"} -

- -

$_aslist1{name="noresamplelist"}

- -

$noresamplelist{name="noreresamplelist"}

- - $_p1{name="noresamplep"} - $noresamplep{name="noreresamplep"} - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let num1 = - stateVariables[ - stateVariables["/sample1"].replacements[0].componentName - ].stateValues.value; - let num2 = - stateVariables[ - stateVariables["/sample2"].replacements[0].componentName - ].stateValues.value; - expect(Number.isInteger(num1) && num1 >= 2 && num1 <= 100).eq(true); - expect(Number.isInteger(num2) && num2 >= 2 && num2 <= 100).eq(true); - // check numbers are prime - for (let num of [num1, num2]) { - let sqrtnum = Math.sqrt(num); - for (let i = 2; i <= sqrtnum; i++) { - expect(num % i).greaterThan(0); - } - } - - expect( - stateVariables[ - stateVariables["/noresample1"].replacements[0].componentName - ].stateValues.value, - ).eq(num1); - expect( - stateVariables[ - stateVariables["/noresample2"].replacements[0].componentName - ].stateValues.value, - ).eq(num2); - expect( - stateVariables[ - stateVariables["/noreresample1"].replacements[0] - .componentName - ].stateValues.value, - ).eq(num1); - expect( - stateVariables[ - stateVariables["/noreresample2"].replacements[0] - .componentName - ].stateValues.value, - ).eq(num2); - - expect( - stateVariables[ - stateVariables["/noresamplelist"].activeChildren[0] - .componentName - ].stateValues.value, - ).eq(num1); - expect( - stateVariables[ - stateVariables["/noresamplelist"].activeChildren[1] - .componentName - ].stateValues.value, - ).eq(num2); - expect( - stateVariables[ - stateVariables["/noreresamplelist"].activeChildren[0] - .componentName - ].stateValues.value, - ).eq(num1); - expect( - stateVariables[ - stateVariables["/noreresamplelist"].activeChildren[1] - .componentName - ].stateValues.value, - ).eq(num2); - - expect( - stateVariables[ - stateVariables[ - stateVariables["/noresamplep"].activeChildren[0] - .componentName - ].activeChildren[0].componentName - ].stateValues.value, - ).eq(num1); - expect( - stateVariables[ - stateVariables[ - stateVariables["/noresamplep"].activeChildren[0] - .componentName - ].activeChildren[1].componentName - ].stateValues.value, - ).eq(num2); - expect( - stateVariables[ - stateVariables[ - stateVariables["/noreresamplep"].activeChildren[0] - .componentName - ].activeChildren[0].componentName - ].stateValues.value, - ).eq(num1); - expect( - stateVariables[ - stateVariables[ - stateVariables["/noreresamplep"].activeChildren[0] - .componentName - ].activeChildren[1].componentName - ].stateValues.value, - ).eq(num2); - }); - }); - - it("select doesn't change dynamically", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 - - -

- -

- - - -

- -

-

$maxnum2.value{assignNames="maxnum2a"}

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_math1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - - let sample1numbers, sample2numbers; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let sample1replacements = stateVariables["/sample1"].replacements; - let sample2replacements = stateVariables["/sample2"].replacements; - expect(sample1replacements.length).eq(5); - expect(sample2replacements.length).eq(2); - sample1numbers = sample1replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - sample2numbers = sample2replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - - for (let num of sample1numbers) { - expect([2, 3].includes(num)).eq(true); - } - for (let num of sample2numbers) { - expect([2, 3, 5, 7].includes(num)).eq(true); - } - }); - - cy.log("Nothing changes when change mathinputs"); - cy.get(cesc("#\\/numToSelect") + " textarea").type( - `{end}{backspace}7{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/maxnum") + " textarea").type( - `{end}{backspace}11{enter}`, - { - force: true, - }, - ); - cy.get(cesc("#\\/numToSelect2") + " textarea").type( - `{end}{backspace}15{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/maxnum2") + " textarea").type( - `{end}{backspace}{backspace}18{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/maxnum2a")).should("contain.text", "18"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let sample1replacements = stateVariables["/sample1"].replacements; - let sample2replacements = stateVariables["/sample2"].replacements; - - expect( - sample1replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ), - ).eqls(sample1numbers); - expect( - sample2replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ), - ).eqls(sample2numbers); - }); - }); - - it("select doesn't resample in dynamic map", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - How many numbers do you want? -

- - - - - - -

- -

$_map1

-

$_aslist1

- - $p1{name="p4"} - $p2{name="p5"} - $p3{name="p6"} - - $p4{name="p7"} - $p5{name="p8"} - $p6{name="p9"} -

$_mathinput1.value{assignNames="m1"}

- `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let samplednumbers = []; - - cy.log("initially nothing"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - }); - - cy.log("sample one variable"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}1{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "1"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - samplednumbers.push(n1); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - for (let ind = 0; ind < 1; ind++) { - expect( - stateVariables[ - stateVariables[ - stateVariables["/p1"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p2"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p3"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p4"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p5"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p6"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p7"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p8"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p9"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - } - }); - - cy.log("go back to nothing"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}0{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "0"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - }); - - cy.log("get same number back"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}1{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "1"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - expect(n1).eq(samplednumbers[0]); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - - for (let ind = 0; ind < 1; ind++) { - expect( - stateVariables[ - stateVariables[ - stateVariables["/p1"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p2"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p3"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p4"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p5"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p6"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p7"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p8"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p9"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - } - }); - - cy.log("get two more samples"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}3{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "3"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - let n2 = stateVariables["/b/n"].stateValues.value; - let n3 = stateVariables["/c/n"].stateValues.value; - expect(n1).eq(samplednumbers[0]); - samplednumbers.push(n2); - samplednumbers.push(n3); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - for (let ind = 0; ind < 3; ind++) { - expect( - stateVariables[ - stateVariables[ - stateVariables["/p1"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p2"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p3"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p4"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p5"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p6"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p7"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p8"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p9"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - } - }); - - cy.log("go back to nothing"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}0{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "0"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - }); - - cy.log("get first two numbers back"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}2{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "2"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - let n2 = stateVariables["/b/n"].stateValues.value; - expect(n1).eq(samplednumbers[0]); - expect(n2).eq(samplednumbers[1]); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - - for (let ind = 0; ind < 2; ind++) { - expect( - stateVariables[ - stateVariables[ - stateVariables["/p1"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p2"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p3"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p4"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p5"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p6"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p7"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p8"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p9"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - } - }); - - cy.log("get six total samples"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}6{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "6"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - let n2 = stateVariables["/b/n"].stateValues.value; - let n3 = stateVariables["/c/n"].stateValues.value; - let n4 = stateVariables["/d/n"].stateValues.value; - let n5 = stateVariables["/e/n"].stateValues.value; - let n6 = stateVariables["/f/n"].stateValues.value; - expect(n1).eq(samplednumbers[0]); - expect(n2).eq(samplednumbers[1]); - expect(n3).eq(samplednumbers[2]); - samplednumbers.push(n4); - samplednumbers.push(n5); - samplednumbers.push(n6); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - for (let ind = 0; ind < 6; ind++) { - expect( - stateVariables[ - stateVariables[ - stateVariables["/p1"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p2"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p3"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p4"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p5"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p6"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p7"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p8"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p9"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - } - }); - - cy.log("go back to nothing"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}0{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "0"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - }); - - cy.log("get all six back"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}6{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "6"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - let n2 = stateVariables["/b/n"].stateValues.value; - let n3 = stateVariables["/c/n"].stateValues.value; - let n4 = stateVariables["/d/n"].stateValues.value; - let n5 = stateVariables["/e/n"].stateValues.value; - let n6 = stateVariables["/f/n"].stateValues.value; - expect(n1).eq(samplednumbers[0]); - expect(n2).eq(samplednumbers[1]); - expect(n3).eq(samplednumbers[2]); - expect(n4).eq(samplednumbers[3]); - expect(n5).eq(samplednumbers[4]); - expect(n6).eq(samplednumbers[5]); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - for (let ind = 0; ind < 6; ind++) { - expect( - stateVariables[ - stateVariables[ - stateVariables["/p1"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p2"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p3"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p4"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p5"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p6"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p7"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p8"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p9"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - } - }); - }); - - it("select prime numbers and sort", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- -

$_aslist1{name="aslist2"}

- $_p1{name="p3"} - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let lastnumber = -20; - let originalnumbers = stateVariables[ - "/_selectprimenumbers1" - ].replacements.map((x) => stateVariables[x.componentName]); - let secondnumbers = stateVariables["/aslist2"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - let thirdnumbers = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map((x) => stateVariables[x.componentName]); - for (let i = 0; i < 20; i++) { - let newnumber = originalnumbers[i].stateValues.value; - expect(newnumber).gte(lastnumber); - lastnumber = newnumber; - expect(secondnumbers[i].stateValues.value).eq(newnumber); - expect(thirdnumbers[i].stateValues.value).eq(newnumber); - } - }); - }); - - it("select a few prime numbers and sort", () => { - // Note: checking to make sure unique variants doesn't mess this up - // (Currently we have turned off unique variants for sort results - // but this test should still pass if we implement it) - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- -

$_aslist1{name="aslist2"}

- $_p1{name="p3"} - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let lastnumber = -20; - let originalnumbers = stateVariables[ - "/_selectprimenumbers1" - ].replacements.map((x) => stateVariables[x.componentName]); - let secondnumbers = stateVariables["/aslist2"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - let thirdnumbers = stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.map((x) => stateVariables[x.componentName]); - for (let i = 0; i < 3; i++) { - let newnumber = originalnumbers[i].stateValues.value; - expect(newnumber).gte(lastnumber); - lastnumber = newnumber; - expect(secondnumbers[i].stateValues.value).eq(newnumber); - expect(thirdnumbers[i].stateValues.value).eq(newnumber); - } - }); - }); - - it("selectprimenumbers hides dynamically", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - -

,

-

$c, $d

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let c = await stateVariables["/c"].stateValues.value; - let d = await stateVariables["/d"].stateValues.value; - expect([2, 3, 5, 7].includes(c)).eq(true); - expect([2, 3, 5, 7].includes(d)).eq(true); - - cy.get(cesc(`#\\/_p1`)).should("have.text", `${c}, `); - cy.get(cesc(`#\\/_p2`)).should("have.text", `${c}, ${d}`); - - cy.get(cesc("#\\/h1")).click(); - cy.get(cesc("#\\/h2")).click(); - - cy.get(cesc(`#\\/_p1`)).should("have.text", `, ${d}`); - cy.get(cesc(`#\\/_p2`)).should("have.text", `${c}, ${d}`); - - cy.get(cesc("#\\/h1")).click(); - cy.get(cesc("#\\/h2")).click(); - - cy.get(cesc(`#\\/_p1`)).should("have.text", `${c}, `); - cy.get(cesc(`#\\/_p2`)).should("have.text", `${c}, ${d}`); - }); - }); - - it("numToSelect from selectprimenumbers", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

n1 =

-

nums =

-

a1=$a1, b1=$b1, c1=$c1, d1=$d1, e1=$e1

- -

n2 =

-

nums =

-

a2=$a2, b2=$b2, c2=$c2, d2=$d2, e2=$e2

- -

n3 =

-

nums =

-

a3=$a3, b3=$b3, c3=$c3, d3=$d3, e3=$e3

- -

n4 =

-

nums =

-

a4=$a4, b4=$b4, c4=$c4, d4=$d4, e4=$e4

- -

n5 =

-

nums =

-

a5=$a5, b5=$b5, c5=$c5, d5=$d5, e5=$e5

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/n1"].stateValues.value; - let n2 = stateVariables["/n2"].stateValues.value; - let n3 = stateVariables["/n3"].stateValues.value; - let n4 = stateVariables["/n4"].stateValues.value; - let n5 = stateVariables["/n5"].stateValues.value; - - let nums1 = stateVariables["/nums1"].replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let nums2 = stateVariables["/nums2"].replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let nums3 = stateVariables["/nums3"].replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let nums4 = stateVariables["/nums4"].replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let nums5 = stateVariables["/nums5"].replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - - expect(nums1.length).eq(n1); - expect(nums2.length).eq(n2); - expect(nums3.length).eq(n3); - expect(nums4.length).eq(n4); - expect(nums5.length).eq(n5); - - nums1.length = 5; - nums2.length = 5; - nums3.length = 5; - nums4.length = 5; - nums5.length = 5; - - nums1.fill("", n1); - nums2.fill("", n2); - nums3.fill("", n3); - nums4.fill("", n4); - nums5.fill("", n5); - - let l = ["a", "b", "c", "d", "e"]; - - cy.get(cesc("#\\/p1")).should( - "have.text", - nums1.map((v, i) => `${l[i]}1=${v}`).join(", "), - ); - cy.get(cesc("#\\/p2")).should( - "have.text", - nums2.map((v, i) => `${l[i]}2=${v}`).join(", "), - ); - cy.get(cesc("#\\/p3")).should( - "have.text", - nums3.map((v, i) => `${l[i]}3=${v}`).join(", "), - ); - cy.get(cesc("#\\/p4")).should( - "have.text", - nums4.map((v, i) => `${l[i]}4=${v}`).join(", "), - ); - cy.get(cesc("#\\/p5")).should( - "have.text", - nums5.map((v, i) => `${l[i]}5=${v}`).join(", "), - ); - }); - }); -}); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/selectrandomnumbers.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/selectrandomnumbers.cy.js deleted file mode 100644 index f4cafdef6..000000000 --- a/packages/test-cypress/cypress/e2e/tagSpecific/selectrandomnumbers.cy.js +++ /dev/null @@ -1,3012 +0,0 @@ -import me from "math-expressions"; -import { cesc, cesc2 } from "@doenet/utils"; - -describe("SelectRandomNumbers Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("no parameters, select single uniform random number from 0 to 1", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1{name="map2"} -

- - $_p1{name="p"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables["/_map1"].replacements.map( - (x) => - stateVariables[ - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].replacements[0].componentName - ].stateValues.value, - ); - - expect(samples.length).eq(100); - - for (let sample of samples) { - expect(sample).gt(0); - expect(sample).lte(1); - } - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(0.5, 0.1); - expect(varX).closeTo(1 / 12, 0.02); - - let firstSelect = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSelect.stateValues.mean).closeTo(0.5, 1e-10); - expect(firstSelect.stateValues.variance).closeTo(1 / 12, 1e-10); - expect(firstSelect.stateValues.standardDeviation).closeTo( - Math.sqrt(1 / 12), - 1e-10, - ); - - let copiedSamples = stateVariables["/map2"].replacements.map( - (x) => - stateVariables[ - stateVariables[ - stateVariables[x.componentName].replacements[0] - .componentName - ].replacements[0].componentName - ].stateValues.value, - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("select five uniform random numbers from 0 to 8, only to specified", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1{name="map2"} -

- - $_p1{name="p"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(samples.length).eq(100); - - for (let sample of samples) { - expect(sample).gt(0); - expect(sample).lte(8); - } - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(4, 0.5); - expect(varX).closeTo(8 ** 2 / 12, 1); - - let firstSelect = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSelect.stateValues.mean).closeTo(4, 1e-10); - expect(firstSelect.stateValues.variance).closeTo( - 8 ** 2 / 12, - 1e-10, - ); - expect(firstSelect.stateValues.standardDeviation).closeTo( - Math.sqrt(8 ** 2 / 12), - 1e-10, - ); - - let copiedSamples = stateVariables["/map2"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("select five uniform random numbers from -5 to -4, only from specified", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1{name="map2"} -

- - $_p1{name="p"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(samples.length).eq(100); - - for (let sample of samples) { - expect(sample).gt(-5); - expect(sample).lte(-4); - } - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(-4.5, 0.05); - expect(varX).closeTo(1 / 12, 0.02); - - let firstSelect = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSelect.stateValues.mean).closeTo(-4.5, 1e-10); - expect(firstSelect.stateValues.variance).closeTo(1 / 12, 1e-10); - expect(firstSelect.stateValues.standardDeviation).closeTo( - Math.sqrt(1 / 12), - 1e-10, - ); - - let copiedSamples = stateVariables["/map2"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("select ten uniform random numbers from -4 to -2", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1{name="map2"} -

- - $_p1{name="p"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(samples.length).eq(100); - - for (let sample of samples) { - expect(sample).gt(-4); - expect(sample).lte(-2); - } - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(-3, 0.5); - expect(varX).closeTo(2 ** 2 / 12, 0.5); - - let firstSelect = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSelect.stateValues.mean).closeTo(-3, 1e-10); - expect(firstSelect.stateValues.variance).closeTo( - 2 ** 2 / 12, - 1e-10, - ); - expect(firstSelect.stateValues.standardDeviation).closeTo( - Math.sqrt(2 ** 2 / 12), - 1e-10, - ); - - let copiedSamples = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("select ten uniform random numbers from -2 to -4", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1{name="map2"} -

- - $_p1{name="p"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(samples.length).eq(100); - - for (let sample of samples) { - expect(sample).gt(-4); - expect(sample).lte(-2); - } - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(-3, 0.5); - expect(varX).closeTo(2 ** 2 / 12, 0.5); - - let firstSelect = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSelect.stateValues.mean).closeTo(-3, 1e-10); - expect(firstSelect.stateValues.variance).closeTo( - 2 ** 2 / 12, - 1e-10, - ); - expect(firstSelect.stateValues.standardDeviation).closeTo( - Math.sqrt(2 ** 2 / 12), - 1e-10, - ); - - let copiedSamples = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("select twenty continuous standard normals, no parameters", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1{name="map2"} -

- - $_p1{name="p"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(samples.length).eq(100); - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(0, 0.3); - expect(varX).closeTo(1, 0.5); - - let firstSelect = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSelect.stateValues.mean).closeTo(0, 1e-10); - expect(firstSelect.stateValues.variance).closeTo(1, 1e-10); - expect(firstSelect.stateValues.standardDeviation).closeTo( - Math.sqrt(1), - 1e-10, - ); - - let copiedSamples = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("select five continuous standard normals, unspecified mean 0, standard deviation 10", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1{name="map2"} -

- - $_p1{name="p"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(samples.length).eq(100); - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(0, 3); - expect(varX).closeTo(100, 25); - - let firstSelect = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSelect.stateValues.mean).closeTo(0, 1e-10); - expect(firstSelect.stateValues.variance).closeTo(100, 1e-10); - expect(firstSelect.stateValues.standardDeviation).closeTo( - Math.sqrt(100), - 1e-10, - ); - - let copiedSamples = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("select single continuous standard normal, mean -50, unspecified standard deviation 1", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1{name="map2"} -

- - $_p1{name="p"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(samples.length).eq(100); - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(-50, 0.5); - expect(varX).closeTo(1, 0.4); - - let firstSelect = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSelect.stateValues.mean).closeTo(-50, 1e-10); - expect(firstSelect.stateValues.variance).closeTo(1, 1e-10); - expect(firstSelect.stateValues.standardDeviation).closeTo( - Math.sqrt(1), - 1e-10, - ); - - let copiedSamples = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("select twenty continuous standard normals, mean 100, standard deviation 10", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1{name="map2"} -

- - $_p1{name="p"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(samples.length).eq(100); - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(100, 5); - expect(varX).closeTo(100, 40); - - let firstSelect = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSelect.stateValues.mean).closeTo(100, 1e-10); - expect(firstSelect.stateValues.variance).closeTo(100, 1e-10); - expect(firstSelect.stateValues.standardDeviation).closeTo( - Math.sqrt(100), - 1e-10, - ); - - let copiedSamples = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("select twenty continuous standard normals, mean -3, variance 0.01", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1{name="map2"} -

- - $_p1{name="p"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(samples.length).eq(100); - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(-3, 0.1); - expect(varX).closeTo(0.01, 0.005); - - let firstSelect = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSelect.stateValues.mean).closeTo(-3, 1e-10); - expect(firstSelect.stateValues.variance).closeTo(0.01, 1e-10); - expect(firstSelect.stateValues.standardDeviation).closeTo( - Math.sqrt(0.01), - 1e-10, - ); - - let copiedSamples = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("select single discrete uniform, no parameters, integer from 0 to 1", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1{name="map2"} -

- - $_p1{name="p"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(samples.length).eq(100); - - for (let sample of samples) { - expect([0, 1].includes(sample)).eq(true); - } - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(0.5, 0.15); - expect(varX).closeTo((2 ** 2 - 1) / 12, 0.05); - - let firstSelect = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSelect.stateValues.mean).closeTo(0.5, 1e-10); - expect(firstSelect.stateValues.variance).closeTo( - (2 ** 2 - 1) / 12, - 1e-10, - ); - expect(firstSelect.stateValues.standardDeviation).closeTo( - Math.sqrt((2 ** 2 - 1) / 12), - 1e-10, - ); - - let copiedSamples = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("select single discrete uniform, from 0.5 to 5.5, only to specified", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1{name="map2"} -

- - $_p1{name="p"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(samples.length).eq(100); - - for (let sample of samples) { - expect([0.5, 1.5, 2.5, 3.5, 4.5, 5.5].includes(sample)).eq( - true, - ); - } - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(3, 0.2); - expect(varX).closeTo((6 ** 2 - 1) / 12, 1); - - let firstSelect = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSelect.stateValues.mean).closeTo(3, 1e-10); - expect(firstSelect.stateValues.variance).closeTo( - (6 ** 2 - 1) / 12, - 1e-10, - ); - expect(firstSelect.stateValues.standardDeviation).closeTo( - Math.sqrt((6 ** 2 - 1) / 12), - 1e-10, - ); - - let copiedSamples = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("select single discrete uniform, from 8.5 to 9.5, only from specified", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1{name="map2"} -

- - $_p1{name="p"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(samples.length).eq(100); - - for (let sample of samples) { - expect([8.5, 9.5].includes(sample)).eq(true); - } - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(9, 0.1); - expect(varX).closeTo((2 ** 2 - 1) / 12, 0.05); - - let firstSelect = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSelect.stateValues.mean).closeTo(9, 1e-10); - expect(firstSelect.stateValues.variance).closeTo( - (2 ** 2 - 1) / 12, - 1e-10, - ); - expect(firstSelect.stateValues.standardDeviation).closeTo( - Math.sqrt((2 ** 2 - 1) / 12), - 1e-10, - ); - - let copiedSamples = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("select five integers from -3 to 5", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1{name="map2"} -

- - $_p1{name="p"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(samples.length).eq(100); - - for (let sample of samples) { - expect([-3, -2, -1, 0, 1, 2, 3, 4, 5].includes(sample)).eq( - true, - ); - } - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(1, 0.5); - expect(varX).closeTo((9 ** 2 - 1) / 12, 1.5); - - let firstSelect = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSelect.stateValues.mean).closeTo(1, 1e-10); - expect(firstSelect.stateValues.variance).closeTo( - (9 ** 2 - 1) / 12, - 1e-10, - ); - expect(firstSelect.stateValues.standardDeviation).closeTo( - Math.sqrt((9 ** 2 - 1) / 12), - 1e-10, - ); - - let copiedSamples = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("select five integers from 5 to -3 gives nothing", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1{name="map2"} -

- - $_p1{name="p"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(samples.length).eq(0); - - let copiedSamples = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("select 10 odd integers from -3 to 5", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- - - - -

- -

- $_map1{name="map2"} -

- - $_p1{name="p"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let samples = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(samples.length).eq(100); - - for (let sample of samples) { - expect([-3, -1, 1, 3, 5].includes(sample)).eq(true); - } - - let meanX = me.math.mean(samples); - let varX = me.math.variance(samples, "uncorrected"); - - expect(meanX).closeTo(1, 0.8); - expect(varX).closeTo(((5 ** 2 - 1) * 2 ** 2) / 12, 2); - - let firstSelect = - stateVariables[ - stateVariables[ - stateVariables["/_map1"].replacements[0].componentName - ].replacements[0].componentName - ]; - expect(firstSelect.stateValues.mean).closeTo(1, 1e-10); - expect(firstSelect.stateValues.variance).closeTo( - ((5 ** 2 - 1) * 2 ** 2) / 12, - 1e-10, - ); - expect(firstSelect.stateValues.standardDeviation).closeTo( - Math.sqrt(((5 ** 2 - 1) * 2 ** 2) / 12), - 1e-10, - ); - - let copiedSamples = stateVariables["/_map1"].replacements.reduce( - (a, c) => [ - ...a, - ...stateVariables[ - stateVariables[c.componentName].replacements[0] - .componentName - ].replacements.map( - (y) => - stateVariables[y.componentName].stateValues.value, - ), - ], - [], - ); - expect(copiedSamples).eqls(samples); - - let copiedCopiedSamples = stateVariables[ - stateVariables["/p"].activeChildren[0].componentName - ].activeChildren.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - expect(copiedCopiedSamples).eqls(samples); - }); - }); - - it("asList", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let results = []; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - results.push(stateVariables["/u"].stateValues.value); - results.push(stateVariables["/v"].stateValues.value); - results.push(stateVariables["/w"].stateValues.value); - results.push(stateVariables["/x"].stateValues.value); - results.push(stateVariables["/y"].stateValues.value); - - for (let num of results) { - expect(num).gte(175).lte(205); - } - - let roundedResults = results.map((x) => Math.round(x * 100) / 100); - cy.get(cesc2("#/_p1")).should( - "have.text", - roundedResults.join(", "), - ); - cy.get(cesc2("#/_p2")).should("have.text", roundedResults.join("")); - }); - }); - - it("selected number doesn't change dynamically", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

- -

- - - -

- -

-

$maxnum2{name="maxnum2a"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let sample1numbers, sample2numbers; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let sample1replacements = stateVariables["/sample1"].replacements; - let sample2replacements = stateVariables["/sample2"].replacements; - expect(sample1replacements.length).eq(20); - expect(sample2replacements.length).eq(10); - sample1numbers = sample1replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - sample2numbers = sample2replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - - for (let num of sample1numbers) { - expect(num).gte(0); - expect(num).lt(10); - } - for (let num of sample2numbers) { - expect([0, 1, 2, 3, 4].includes(num)).eq(true); - } - }); - - cy.log("Nothing changes when change mathinputs"); - cy.get(cesc("#\\/numToSelect") + " textarea").type( - `{end}{backspace}{backspace}7{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/maxnum") + " textarea").type( - `{end}{backspace}{backspace}11{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/numToSelect2") + " textarea").type( - `{end}{backspace}{backspace}15{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/maxnum2") + " textarea").type( - `{end}{backspace}{backspace}18{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/maxnum2a")).should("contain.text", "18"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let sample1replacements = stateVariables["/sample1"].replacements; - let sample2replacements = stateVariables["/sample2"].replacements; - - expect( - sample1replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ), - ).eqls(sample1numbers); - expect( - sample2replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ), - ).eqls(sample2numbers); - }); - }); - - it("random number doesn't resample in dynamic map", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - How many numbers do you want? -

- - - - - - -

- -

$_map1{name="map2"}

-

$_aslist1

- - $p1{name="p4"} - $p2{name="p5"} - $p3{name="p6"} - - $p4{name="p7"} - $p5{name="p8"} - $p6{name="p9"} -

$_mathinput1{name="m1"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let samplednumbers = []; - - cy.log("initially nothing"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - }); - - cy.log("sample one variable"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}1{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "1"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - samplednumbers.push(n1); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - for (let ind = 0; ind < 1; ind++) { - expect( - stateVariables[ - stateVariables[ - stateVariables["/p1"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p2"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p3"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p4"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p5"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p6"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p7"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p8"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p9"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - } - }); - - cy.log("go back to nothing"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}0{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "0"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - }); - - cy.log("get same number back"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}1{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "1"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - expect(n1).eq(samplednumbers[0]); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(1); - - for (let ind = 0; ind < 1; ind++) { - expect( - stateVariables[ - stateVariables[ - stateVariables["/p1"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p2"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p3"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p4"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p5"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p6"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p7"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p8"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p9"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - } - }); - - cy.log("get two more samples"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}3{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "3"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - let n2 = stateVariables["/b/n"].stateValues.value; - let n3 = stateVariables["/c/n"].stateValues.value; - expect(n1).eq(samplednumbers[0]); - samplednumbers.push(n2); - samplednumbers.push(n3); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(3); - for (let ind = 0; ind < 3; ind++) { - expect( - stateVariables[ - stateVariables[ - stateVariables["/p1"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p2"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p3"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p4"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p5"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p6"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p7"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p8"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p9"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - } - }); - - cy.log("go back to nothing"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}0{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "0"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - }); - - cy.log("get first two numbers back"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}2{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "2"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - let n2 = stateVariables["/b/n"].stateValues.value; - expect(n1).eq(samplednumbers[0]); - expect(n2).eq(samplednumbers[1]); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(2); - - for (let ind = 0; ind < 2; ind++) { - expect( - stateVariables[ - stateVariables[ - stateVariables["/p1"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p2"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p3"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p4"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p5"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p6"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p7"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p8"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p9"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - } - }); - - cy.log("get six total samples"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}6{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "6"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - let n2 = stateVariables["/b/n"].stateValues.value; - let n3 = stateVariables["/c/n"].stateValues.value; - let n4 = stateVariables["/d/n"].stateValues.value; - let n5 = stateVariables["/e/n"].stateValues.value; - let n6 = stateVariables["/f/n"].stateValues.value; - expect(n1).eq(samplednumbers[0]); - expect(n2).eq(samplednumbers[1]); - expect(n3).eq(samplednumbers[2]); - samplednumbers.push(n4); - samplednumbers.push(n5); - samplednumbers.push(n6); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - for (let ind = 0; ind < 6; ind++) { - expect( - stateVariables[ - stateVariables[ - stateVariables["/p1"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p2"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p3"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p4"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p5"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p6"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p7"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p8"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p9"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - } - }); - - cy.log("go back to nothing"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}0{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "0"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(0); - }); - - cy.log("get all six back"); - cy.get(cesc("#\\/_mathinput1") + " textarea").type( - `{end}{backspace}6{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/m1")).should("contain.text", "6"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/a/n"].stateValues.value; - let n2 = stateVariables["/b/n"].stateValues.value; - let n3 = stateVariables["/c/n"].stateValues.value; - let n4 = stateVariables["/d/n"].stateValues.value; - let n5 = stateVariables["/e/n"].stateValues.value; - let n6 = stateVariables["/f/n"].stateValues.value; - expect(n1).eq(samplednumbers[0]); - expect(n2).eq(samplednumbers[1]); - expect(n3).eq(samplednumbers[2]); - expect(n4).eq(samplednumbers[3]); - expect(n5).eq(samplednumbers[4]); - expect(n6).eq(samplednumbers[5]); - expect( - stateVariables[ - stateVariables["/p1"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p2"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p3"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p4"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p5"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p6"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p7"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p8"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - expect( - stateVariables[ - stateVariables["/p9"].activeChildren[0].componentName - ].activeChildren.length, - ).eq(6); - for (let ind = 0; ind < 6; ind++) { - expect( - stateVariables[ - stateVariables[ - stateVariables["/p1"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p2"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p3"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p4"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p5"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p6"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p7"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p8"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - expect( - stateVariables[ - stateVariables[ - stateVariables["/p9"].activeChildren[0] - .componentName - ].activeChildren[ind].componentName - ].stateValues.value, - ).eq(samplednumbers[ind]); - } - }); - }); - - it("select single discrete uniform number, assign name", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

-

$u{name="u2"}

-

$v{name="v2"}

-

$w{name="w2"}

- `, - }, - "*", - ); - }); - - let options = [3, 10]; - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let u = stateVariables["/u"]; - let u2 = stateVariables["/u2"]; - - expect(options.includes(u.stateValues.value)).eq(true); - expect(u.stateValues.value).eq(u2.stateValues.value); - - let v = stateVariables["/v"]; - let v2 = stateVariables["/v2"]; - expect(options.includes(v.stateValues.value)).eq(true); - expect(v.stateValues.value).eq(v2.stateValues.value); - - let w = stateVariables["/w"]; - let w2 = stateVariables["/w2"]; - expect(options.includes(w.stateValues.value)).eq(true); - expect(w.stateValues.value).eq(w2.stateValues.value); - }); - }); - - it("select multiple uniform random numbers, assign names", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- -

-

$u{name="u2"}

-

$v{name="v2"}

-

$w{name="w2"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let results = []; - - for (let ind = 0; ind < 6; ind++) { - cy.get(cesc("#\\/_p1") + " > :nth-child(" + (2 * ind + 4) + ")") - .invoke("text") - .then((text) => { - let num = Number(text); - results[ind] = num; - expect(num).gte(3); - expect(num).lt(13); - }); - } - - cy.log("check by name").then(() => { - cy.get(cesc("#\\/u")).should("have.text", results[0]); - cy.get(cesc("#\\/u2")).should("have.text", results[0]); - cy.get(cesc("#\\/v")).should("have.text", results[1]); - cy.get(cesc("#\\/v2")).should("have.text", results[1]); - cy.get(cesc("#\\/w")).should("have.text", results[2]); - cy.get(cesc("#\\/w2")).should("have.text", results[2]); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let u = stateVariables["/u"]; - let u2 = stateVariables["/u2"]; - expect(u.stateValues.value).closeTo(results[0], 1e-8); - expect(u2.stateValues.value).closeTo(results[0], 1e-8); - - let v = stateVariables["/v"]; - let v2 = stateVariables["/v2"]; - expect(v.stateValues.value).closeTo(results[1], 1e-8); - expect(v2.stateValues.value).closeTo(results[1], 1e-8); - - let w = stateVariables["/w"]; - let w2 = stateVariables["/w2"]; - expect(w.stateValues.value).closeTo(results[2], 1e-8); - expect(w2.stateValues.value).closeTo(results[2], 1e-8); - - let s = stateVariables["/s"]; - expect(s.replacements.length).eq(6); - for (let ind = 0; ind < 6; ind++) { - let r = stateVariables[s.replacements[ind].componentName]; - expect(r.stateValues.value).closeTo(results[ind], 1e-8); - } - }); - }); - - it("select multiple uniform random numbers, assign names, newNamespace", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- -

-

$(s/u{name="u2"})

-

$(s/v{name="v2"})

-

$(s/w{name="w2"})

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let results = []; - - for (let ind = 0; ind < 6; ind++) { - cy.get(cesc("#\\/_p1") + " > :nth-child(" + (2 * ind + 4) + ")") - .invoke("text") - .then((text) => { - let num = Number(text); - results[ind] = num; - expect(num).gte(3); - expect(num).lt(13); - }); - } - - cy.log("check by name").then(() => { - cy.get(cesc("#\\/s\\/u")).should("have.text", results[0]); - cy.get(cesc("#\\/u2")).should("have.text", results[0]); - cy.get(cesc("#\\/s\\/v")).should("have.text", results[1]); - cy.get(cesc("#\\/v2")).should("have.text", results[1]); - cy.get(cesc("#\\/s\\/w")).should("have.text", results[2]); - cy.get(cesc("#\\/w2")).should("have.text", results[2]); - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let u = stateVariables["/s/u"]; - let u2 = stateVariables["/u2"]; - expect(u.stateValues.value).closeTo(results[0], 1e-8); - expect(u2.stateValues.value).closeTo(results[0], 1e-8); - - let v = stateVariables["/s/v"]; - let v2 = stateVariables["/v2"]; - expect(v.stateValues.value).closeTo(results[1], 1e-8); - expect(v2.stateValues.value).closeTo(results[1], 1e-8); - - let w = stateVariables["/s/w"]; - let w2 = stateVariables["/w2"]; - expect(w.stateValues.value).closeTo(results[2], 1e-8); - expect(w2.stateValues.value).closeTo(results[2], 1e-8); - - let s = stateVariables["/s"]; - expect(s.replacements.length).eq(6); - for (let ind = 0; ind < 6; ind++) { - let r = stateVariables[s.replacements[ind].componentName]; - expect(r.stateValues.value).closeTo(results[ind], 1e-8); - } - }); - }); - - it("numToSelect from selectfromsequence", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

n1 =

-

nums =

-

a1=$a1, b1=$b1, c1=$c1, d1=$d1, e1=$e1

- -

n2 =

-

nums =

-

a2=$a2, b2=$b2, c2=$c2, d2=$d2, e2=$e2

- -

n3 =

-

nums =

-

a3=$a3, b3=$b3, c3=$c3, d3=$d3, e3=$e3

- -

n4 =

-

nums =

-

a4=$a4, b4=$b4, c4=$c4, d4=$d4, e4=$e4

- -

n5 =

-

nums =

-

a5=$a5, b5=$b5, c5=$c5, d5=$d5, e5=$e5

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let n1 = stateVariables["/n1"].stateValues.value; - let n2 = stateVariables["/n2"].stateValues.value; - let n3 = stateVariables["/n3"].stateValues.value; - let n4 = stateVariables["/n4"].stateValues.value; - let n5 = stateVariables["/n5"].stateValues.value; - - let nums1 = stateVariables["/nums1"].replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let nums2 = stateVariables["/nums2"].replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let nums3 = stateVariables["/nums3"].replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let nums4 = stateVariables["/nums4"].replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - let nums5 = stateVariables["/nums5"].replacements.map( - (x) => stateVariables[x.componentName].stateValues.value, - ); - - expect(nums1.length).eq(n1); - expect(nums2.length).eq(n2); - expect(nums3.length).eq(n3); - expect(nums4.length).eq(n4); - expect(nums5.length).eq(n5); - - nums1.length = 5; - nums2.length = 5; - nums3.length = 5; - nums4.length = 5; - nums5.length = 5; - - nums1.fill("", n1); - nums2.fill("", n2); - nums3.fill("", n3); - nums4.fill("", n4); - nums5.fill("", n5); - - let l = ["a", "b", "c", "d", "e"]; - - cy.get(cesc("#\\/p1")).should( - "have.text", - nums1 - .map( - (v, i) => - `${l[i]}1=${v ? Math.round(v * 1e9) / 1e9 : ""}`, - ) - .join(", "), - ); - cy.get(cesc("#\\/p2")).should( - "have.text", - nums2 - .map( - (v, i) => - `${l[i]}2=${v ? Math.round(v * 1e9) / 1e9 : ""}`, - ) - .join(", "), - ); - cy.get(cesc("#\\/p3")).should( - "have.text", - nums3 - .map( - (v, i) => - `${l[i]}3=${v ? Math.round(v * 1e9) / 1e9 : ""}`, - ) - .join(", "), - ); - cy.get(cesc("#\\/p4")).should( - "have.text", - nums4 - .map( - (v, i) => - `${l[i]}4=${v ? Math.round(v * 1e9) / 1e9 : ""}`, - ) - .join(", "), - ); - cy.get(cesc("#\\/p5")).should( - "have.text", - nums5 - .map( - (v, i) => - `${l[i]}5=${v ? Math.round(v * 1e9) / 1e9 : ""}`, - ) - .join(", "), - ); - }); - }); - - it("rounding", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

-

- -

$n1

-

$n2

-

$n3

-

$n4

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let n1 = stateVariables["/n1"].stateValues.value; - let n2 = stateVariables["/n2"].stateValues.value; - let n3 = stateVariables["/n3"].stateValues.value; - let n4 = stateVariables["/n4"].stateValues.value; - - cy.get(cesc("#\\/n1")).should( - "have.text", - String(Math.round(n1 * 10 ** 8) / 10 ** 8), - ); - cy.get(cesc("#\\/n2")).should( - "have.text", - String(Math.round(n2 * 10 ** 1) / 10 ** 1), - ); - cy.get(cesc("#\\/n3")).should( - "have.text", - String(Math.round(n3 * 10 ** 3) / 10 ** 3), - ); - cy.get(cesc("#\\/n4")).should("have.text", String(n4) + ".0"); - - cy.get(cesc("#\\/n1a")).should( - "have.text", - String(Math.round(n1 * 10 ** 8) / 10 ** 8), - ); - cy.get(cesc("#\\/n2a")).should( - "have.text", - String(Math.round(n2 * 10 ** 1) / 10 ** 1), - ); - cy.get(cesc("#\\/n3a")).should( - "have.text", - String(Math.round(n3 * 10 ** 3) / 10 ** 3), - ); - cy.get(cesc("#\\/n4a")).should("have.text", String(n4) + ".0"); - }); - }); -}); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/sequence.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/sequence.cy.js deleted file mode 100644 index 05106af38..000000000 --- a/packages/test-cypress/cypress/e2e/tagSpecific/sequence.cy.js +++ /dev/null @@ -1,2406 +0,0 @@ -import me from "math-expressions"; -import { cesc, cesc2 } from "@doenet/utils"; - -describe("Sequence Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("number sequence, no parameters", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - // to wait for page to load - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(10); - for (let i = 0; i < 10; i++) { - expect(children[i].stateValues.value).eq(i + 1); - } - }); - }); - - it("number sequence, just from", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(10); - for (let i = 0; i < 10; i++) { - expect(children[i].stateValues.value).eq(i - 4); - } - }); - }); - - it("number sequence, just to", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(3); - for (let i = 0; i < 3; i++) { - expect(children[i].stateValues.value).eq(3 + i - 2); - } - }); - }); - - it("number sequence, just step", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(10); - for (let i = 0; i < 10; i++) { - expect(children[i].stateValues.value).eq(1 + i * -2); - } - }); - }); - - it("number sequence, just length", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(5); - for (let i = 0; i < 5; i++) { - expect(children[i].stateValues.value).eq(1 + i); - } - }); - }); - - it("number sequence, from and to", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(8); - for (let i = 0; i < 8; i++) { - expect(children[i].stateValues.value).eq(-3 + i); - } - }); - }); - - it("number sequence, from and to, not matching", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(8); - for (let i = 0; i < 8; i++) { - expect(children[i].stateValues.value).eq(-3 + i); - } - }); - }); - - it("number sequence, from and to, adjust for round-off error", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(8); - for (let i = 0; i < 8; i++) { - expect(children[i].stateValues.value).eq(i + 1); - } - }); - }); - - it("math sequence, from and to, adjust for round-off error", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(8); - for (let i = 0; i < 8; i++) { - expect(children[i].stateValues.value).eq(i + 1); - } - }); - }); - - it("number sequence, from and step", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(10); - for (let i = 0; i < 10; i++) { - expect(children[i].stateValues.value).eq(2 + i * -4); - } - }); - }); - - it("number sequence, from and length", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(3); - for (let i = 0; i < 3; i++) { - expect(children[i].stateValues.value).eq(11 + i); - } - }); - }); - - it("number sequence, to and step", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(7); - for (let i = 0; i < 7; i++) { - expect(children[i].stateValues.value).eq(21 + 3 * (i - 6)); - } - }); - }); - - it("number sequence, to and step, adjust for round-off error", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(5); - for (let i = 0; i < 5; i++) { - expect( - Math.abs(children[i].stateValues.value - (1 + i * 0.1)), - ).lessThan(1e-14); - } - }); - }); - - it("math sequence, to and step, adjust for round-off error", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(5); - for (let i = 0; i < 5; i++) { - expect( - Math.abs(children[i].stateValues.value - (1 + i * 0.1)), - ).lessThan(1e-14); - } - }); - }); - - it("number sequence, to and length", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(4); - for (let i = 0; i < 4; i++) { - expect(children[i].stateValues.value).eq(-8 + (i - 3)); - } - }); - }); - - it("number sequence, step and length", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(6); - for (let i = 0; i < 6; i++) { - expect(children[i].stateValues.value).eq(1 + 5 * i); - } - }); - }); - - it("number sequence, from, to, and step", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(4); - for (let i = 0; i < 4; i++) { - expect(children[i].stateValues.value).eq(9 - 2 * i); - } - }); - }); - - it("number sequence, from, to, and step, adjust for round-off errors", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let sequence = [0.2, 0.3, 0.4, 0.5]; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(4); - for (let i = 0; i < 4; i++) { - expect( - Math.abs(children[i].stateValues.value - sequence[i]), - ).lessThan(1e-14); - } - }); - }); - - it("math sequence, from, to, and step, adjust for round-off errors", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let sequence = [0.2, 0.3, 0.4, 0.5]; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(4); - for (let i = 0; i < 4; i++) { - expect( - Math.abs(children[i].stateValues.value - sequence[i]), - ).lessThan(1e-14); - } - }); - }); - - it("number sequence, from, to, and length", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(6); - for (let i = 0; i < 6; i++) { - expect(children[i].stateValues.value).eq(-5 + 2 * i); - } - }); - }); - - it("number sequence, from, step, and length", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(5); - for (let i = 0; i < 5; i++) { - expect(children[i].stateValues.value).eq(8 - 2 * i); - } - }); - }); - - it("number sequence, to, step, and length", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(5); - for (let i = 0; i < 5; i++) { - expect(children[i].stateValues.value).eq(8 - 2 * (i - 4)); - } - }); - }); - - it("letters sequence, lowercase", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(5); - expect(children[0].stateValues.value).eq("c"); - expect(children[1].stateValues.value).eq("f"); - expect(children[2].stateValues.value).eq("i"); - expect(children[3].stateValues.value).eq("l"); - expect(children[4].stateValues.value).eq("o"); - }); - }); - - it("letters sequence, uppercase", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(5); - expect(children[0].stateValues.value).eq("Y"); - expect(children[1].stateValues.value).eq("U"); - expect(children[2].stateValues.value).eq("Q"); - expect(children[3].stateValues.value).eq("M"); - expect(children[4].stateValues.value).eq("I"); - }); - }); - - it("letters sequence, multicharacter", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(4); - expect(children[0].stateValues.value).eq("az"); - expect(children[1].stateValues.value).eq("bc"); - expect(children[2].stateValues.value).eq("bf"); - expect(children[3].stateValues.value).eq("bi"); - }); - }); - - it("letters sequence, stays valid", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(6); - expect(children[0].stateValues.value).eq("b"); - expect(children[1].stateValues.value).eq("e"); - expect(children[2].stateValues.value).eq("h"); - expect(children[3].stateValues.value).eq("k"); - expect(children[4].stateValues.value).eq("n"); - expect(children[5].stateValues.value).eq("q"); - }); - }); - - it("letters sequence, no parameters", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(10); - expect(children[0].stateValues.value).eq("a"); - expect(children[1].stateValues.value).eq("b"); - expect(children[2].stateValues.value).eq("c"); - expect(children[3].stateValues.value).eq("d"); - expect(children[4].stateValues.value).eq("e"); - expect(children[5].stateValues.value).eq("f"); - expect(children[6].stateValues.value).eq("g"); - expect(children[7].stateValues.value).eq("h"); - expect(children[8].stateValues.value).eq("i"); - expect(children[9].stateValues.value).eq("j"); - }); - }); - - it("math sequence, calculate step", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(4); - expect(children[0].stateValues.value).eqls(["*", 3, "x"]); - expect(children[1].stateValues.value).eqls([ - "+", - ["*", 2, "x"], - "y", - ]); - expect(children[2].stateValues.value).eqls([ - "+", - "x", - ["*", 2, "y"], - ]); - expect(children[3].stateValues.value).eqls(["*", 3, "y"]); - }); - }); - - it("number sequence, excludes", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

Also exclude:

-

$exclude2.value{assignNames="exclude2a"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(8); - let ind = 0; - for (let i = 0; i < 10; i++) { - if (i == 1 || i == 7) { - continue; - } - expect(children[ind].stateValues.value).eq(i - 1); - ind++; - } - }); - - cy.log("also exclude 7"); - cy.get(cesc("#\\/exclude2") + " textarea").type( - `{end}{backspace}7{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/exclude2a")).should("contain.text", "7"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(7); - let ind = 0; - for (let i = 0; i < 10; i++) { - if (i == 1 || i == 7 || i == 8) { - continue; - } - expect(children[ind].stateValues.value).eq(i - 1); - ind++; - } - }); - - cy.log("also exclude 6 twice"); - cy.get(cesc("#\\/exclude2") + " textarea").type( - `{end}{backspace}6{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/exclude2a")).should("contain.text", "6"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(8); - let ind = 0; - for (let i = 0; i < 10; i++) { - if (i == 1 || i == 7) { - continue; - } - expect(children[ind].stateValues.value).eq(i - 1); - ind++; - } - }); - - cy.log("also exclude 12"); - cy.get(cesc("#\\/exclude2") + " textarea").type( - `{end}{backspace}12{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/exclude2a")).should("contain.text", "12"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(8); - let ind = 0; - for (let i = 0; i < 10; i++) { - if (i == 1 || i == 7) { - continue; - } - expect(children[ind].stateValues.value).eq(i - 1); - ind++; - } - }); - - cy.log("also exclude 3"); - cy.get(cesc("#\\/exclude2") + " textarea").type( - `{end}{backspace}{backspace}3{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/exclude2a")).should("contain.text", "3"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(7); - let ind = 0; - for (let i = 0; i < 10; i++) { - if (i == 1 || i == 7 || i == 4) { - continue; - } - expect(children[ind].stateValues.value).eq(i - 1); - ind++; - } - }); - - cy.log("don't exclude anything else"); - cy.get(cesc("#\\/exclude2") + " textarea").type( - `{end}{backspace}{enter}`, - { - force: true, - }, - ); - cy.get(cesc("#\\/exclude2a")).should("not.contain.text", "3"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(8); - let ind = 0; - for (let i = 0; i < 10; i++) { - if (i == 1 || i == 7) { - continue; - } - expect(children[ind].stateValues.value).eq(i - 1); - ind++; - } - }); - }); - - it("number sequence, excludes, adjust for round-off errors", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let sequence = [0.1, 0.2, 0.4, 0.5, 0.8]; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(5); - for (let i = 0; i < 5; i++) { - expect( - Math.abs(children[i].stateValues.value - sequence[i]), - ).lessThan(1e-14); - } - }); - }); - - it("letters sequence, excludes", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

Also exclude:

-

$e.value{assignNames="ea"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(8); - let ind = 0; - for (let i = 0; i < 10; i++) { - if (i == 1 || i == 5) { - continue; - } - expect(children[ind].stateValues.value).eq( - String.fromCharCode(97 + i), - ); - ind++; - } - }); - - cy.log("also exclude i"); - cy.get(cesc("#\\/e_input")).clear().type(`i{enter}`); - cy.get(cesc("#\\/ea")).should("contain.text", "i"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(7); - let ind = 0; - for (let i = 0; i < 10; i++) { - if (i == 1 || i == 5 || i == 8) { - continue; - } - expect(children[ind].stateValues.value).eq( - String.fromCharCode(97 + i), - ); - ind++; - } - }); - - cy.log("also exclude f twice"); - cy.get(cesc("#\\/e_input")).clear().type(`f{enter}`); - cy.get(cesc("#\\/ea")).should("contain.text", "f"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(8); - let ind = 0; - for (let i = 0; i < 10; i++) { - if (i == 1 || i == 5) { - continue; - } - expect(children[ind].stateValues.value).eq( - String.fromCharCode(97 + i), - ); - ind++; - } - }); - - cy.log("also exclude l"); - cy.get(cesc("#\\/e_input")).clear().type(`l{enter}`); - cy.get(cesc("#\\/ea")).should("contain.text", "l"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(8); - let ind = 0; - for (let i = 0; i < 10; i++) { - if (i == 1 || i == 5) { - continue; - } - expect(children[ind].stateValues.value).eq( - String.fromCharCode(97 + i), - ); - ind++; - } - }); - - cy.log("also exclude C"); - cy.get(cesc("#\\/e_input")).clear().type(`C{enter}`); - cy.get(cesc("#\\/ea")).should("contain.text", "C"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(7); - let ind = 0; - for (let i = 0; i < 10; i++) { - if (i == 1 || i == 5 || i == 2) { - continue; - } - expect(children[ind].stateValues.value).eq( - String.fromCharCode(97 + i), - ); - ind++; - } - }); - - cy.log("don't exclude anything else"); - cy.get(cesc("#\\/e_input")).clear().type(`{enter}`); - cy.get(cesc("#\\/ea")).should("have.text", ""); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(8); - let ind = 0; - for (let i = 0; i < 10; i++) { - if (i == 1 || i == 5) { - continue; - } - expect(children[ind].stateValues.value).eq( - String.fromCharCode(97 + i), - ); - ind++; - } - }); - }); - - it("math sequence, excludes", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - -

Also exclude:

-

$e.value{assignNames="ea"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(8); - let ind = 0; - for (let i = 0; i < 10; i++) { - if (i == 1 || i == 5) { - continue; - } - expect( - me - .fromAst(children[ind].stateValues.value) - .equals(me.fromText((1 + i).toString() + "x")), - ).eq(true); - ind++; - } - }); - - cy.log("also exclude 9x"); - cy.get(cesc("#\\/e") + " textarea").type(`{end}{backspace}9x{enter}`, { - force: true, - }); - cy.get(cesc("#\\/ea")).should("contain.text", "9x"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(7); - let ind = 0; - for (let i = 0; i < 10; i++) { - if (i == 1 || i == 5 || i == 8) { - continue; - } - expect( - me - .fromAst(children[ind].stateValues.value) - .equals(me.fromText((1 + i).toString() + "x")), - ).eq(true); - ind++; - } - }); - - cy.log("also exclude 6x twice"); - cy.get(cesc("#\\/e") + " textarea").type( - `{end}{backspace}{backspace}6x{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/ea")).should("contain.text", "6x"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(8); - let ind = 0; - for (let i = 0; i < 10; i++) { - if (i == 1 || i == 5) { - continue; - } - expect( - me - .fromAst(children[ind].stateValues.value) - .equals(me.fromText((1 + i).toString() + "x")), - ).eq(true); - ind++; - } - }); - - cy.log("also exclude 12x"); - cy.get(cesc("#\\/e") + " textarea").type( - `{end}{backspace}{backspace}12x{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/ea")).should("contain.text", "12x"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(8); - let ind = 0; - for (let i = 0; i < 10; i++) { - if (i == 1 || i == 5) { - continue; - } - expect( - me - .fromAst(children[ind].stateValues.value) - .equals(me.fromText((1 + i).toString() + "x")), - ).eq(true); - ind++; - } - }); - - cy.log("also exclude 3x"); - cy.get(cesc("#\\/e") + " textarea").type( - `{ctrl+home}{shift+end}{backspace}3x{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/ea")).should("contain.text", "3x"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(7); - let ind = 0; - for (let i = 0; i < 10; i++) { - if (i == 1 || i == 5 || i == 2) { - continue; - } - expect( - me - .fromAst(children[ind].stateValues.value) - .equals(me.fromText((1 + i).toString() + "x")), - ).eq(true); - ind++; - } - }); - - cy.log("don't exclude anything else"); - cy.get(cesc("#\\/e") + " textarea").type( - `{end}{backspace}{backspace}{enter}`, - { force: true }, - ); - cy.get(cesc("#\\/ea")).should("not.contain.text", "3x"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(8); - let ind = 0; - for (let i = 0; i < 10; i++) { - if (i == 1 || i == 5) { - continue; - } - expect( - me - .fromAst(children[ind].stateValues.value) - .equals(me.fromText((1 + i).toString() + "x")), - ).eq(true); - ind++; - } - }); - }); - - it("math sequence, excludes, adjust for round-off errors", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let sequence = [0.1, 0.2, 0.4, 0.5, 0.8]; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(5); - for (let i = 0; i < 5; i++) { - expect( - Math.abs(children[i].stateValues.value - sequence[i]), - ).lessThan(1e-14); - } - }); - }); - - it("sequence of decimals rounds on display", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.log("Round when displaying to show 10ths correctly"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let replacements = stateVariables["/_sequence1"].replacements; - - for (let i = 0; i < 11; i++) { - cy.get(cesc2("#" + replacements[i].componentName)) - .invoke("text") - .then((text) => { - expect(text.trim()).equal((i / 10).toString()); - }); - } - }); - - cy.log("Don't round internaly"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let replacements = stateVariables["/_sequence1"].replacements.map( - (x) => stateVariables[x.componentName], - ); - - for (let i = 0; i < 11; i++) { - expect(replacements[i].stateValues.value).eq(0.1 * i); - } - }); - }); - - it("sequence with number operators ", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 5 - 10 - - - - - $n11 - - - $m+311 - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let replacements = stateVariables["/_sequence1"].replacements; - for (let i = 0; i < 9; i++) { - cy.get(cesc2("#" + replacements[i].componentName)) - .invoke("text") - .then((text) => { - expect(text.trim()).equal((i + 5).toString()); - }); - } - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let replacements = stateVariables["/_sequence1"].replacements.map( - (x) => stateVariables[x.componentName], - ); - for (let i = 0; i < 9; i++) { - expect(replacements[i].stateValues.value).eq(i + 5); - } - }); - }); - - it("initially invalid to", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

$n.value{assignNames="n2"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.log("sequence starts off invalid"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_sequence1"].stateValues.validSequence).eq( - false, - ); - expect(stateVariables["/_sequence1"].replacements.length).eq(0); - }); - - cy.get(cesc("#\\/n") + " textarea").type("2{enter}", { force: true }); - cy.get(cesc("#\\/n2")).should("contain.text", "2"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let number1 = stateVariables["/_sequence1"].replacements[0]; - let number1Name = number1.componentName; - let number1Anchor = cesc2("#" + number1Name); - - cy.get(number1Anchor).should("have.text", "2"); - - cy.window().then(async (win) => { - expect( - stateVariables["/_sequence1"].stateValues.validSequence, - ).eq(true); - expect(stateVariables["/_sequence1"].replacements.length).eq(1); - }); - }); - }); - - it("number sequence, excluding every 3 plus another", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/_p1")).should("have.text", "1, 3, 4, 6, 7, 10"); - }); - - it("number sequence, excluding from different sources", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 4 62 87 -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/_p1")).should("have.text", "1, 3, 5, 9, 10"); - }); - - it("sequences hide dynamically", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - -

Length of sequence 1:

-

Length of sequence 2:

- -

sequence 1:

-

sequence 2:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/s1")).should("have.text", "sequence 1: 1, 2, 3, 4"); - cy.get(cesc("#\\/s2")).should("have.text", "sequence 2: "); - - cy.get(cesc("#\\/n1") + " textarea").type("{end}{backspace}6{enter}", { - force: true, - }); - cy.get(cesc("#\\/n2") + " textarea").type("{end}{backspace}6{enter}", { - force: true, - }); - - cy.get(cesc("#\\/s1")).should( - "have.text", - "sequence 1: 1, 2, 3, 4, 5, 6", - ); - cy.get(cesc("#\\/s2")).should("have.text", "sequence 2: "); - - cy.get(cesc("#\\/h1")).click(); - cy.get(cesc("#\\/h2")).click(); - - cy.get(cesc("#\\/s1")).should("have.text", "sequence 1: "); - cy.get(cesc("#\\/s2")).should( - "have.text", - "sequence 2: 1, 2, 3, 4, 5, 6", - ); - - cy.get(cesc("#\\/n1") + " textarea").type("{end}{backspace}8{enter}", { - force: true, - }); - cy.get(cesc("#\\/n2") + " textarea").type("{end}{backspace}8{enter}", { - force: true, - }); - - cy.get(cesc("#\\/s1")).should("have.text", "sequence 1: "); - cy.get(cesc("#\\/s2")).should( - "have.text", - "sequence 2: 1, 2, 3, 4, 5, 6, 7, 8", - ); - - cy.get(cesc("#\\/h1")).click(); - cy.get(cesc("#\\/h2")).click(); - - cy.get(cesc("#\\/s1")).should( - "have.text", - "sequence 1: 1, 2, 3, 4, 5, 6, 7, 8", - ); - cy.get(cesc("#\\/s2")).should("have.text", "sequence 2: "); - - cy.get(cesc("#\\/n1") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - cy.get(cesc("#\\/n2") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - - cy.get(cesc("#\\/s1")).should("have.text", "sequence 1: 1, 2, 3"); - cy.get(cesc("#\\/s2")).should("have.text", "sequence 2: "); - - cy.get(cesc("#\\/h1")).click(); - cy.get(cesc("#\\/h2")).click(); - - cy.get(cesc("#\\/s1")).should("have.text", "sequence 1: "); - cy.get(cesc("#\\/s2")).should("have.text", "sequence 2: 1, 2, 3"); - - cy.get(cesc("#\\/n1") + " textarea").type("{end}{backspace}4{enter}", { - force: true, - }); - cy.get(cesc("#\\/n2") + " textarea").type("{end}{backspace}4{enter}", { - force: true, - }); - - cy.get(cesc("#\\/s1")).should("have.text", "sequence 1: "); - cy.get(cesc("#\\/s2")).should("have.text", "sequence 2: 1, 2, 3, 4"); - }); - - it("sequence fixed by default", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

From:

-

Step:

- -

- -

Change first:

-

Change second:

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/thelist")).should("have.text", "1, 3, 5, 7"); - - cy.get(cesc("#\\/a2") + " textarea").type("{end}{backspace}21{enter}", { - force: true, - }); - cy.get(cesc("#\\/thelist")).should("have.text", "1, 3, 5, 7"); - - cy.get(cesc("#\\/b2") + " textarea").type("{end}{backspace}0{enter}", { - force: true, - }); - cy.get(cesc("#\\/thelist")).should("have.text", "1, 3, 5, 7"); - - cy.get(cesc("#\\/from") + " textarea").type( - "{end}{backspace}4{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/thelist")).should("have.text", "4, 6"); - - cy.get(cesc("#\\/a2") + " textarea").type("{end}{backspace}8{enter}", { - force: true, - }); - cy.get(cesc("#\\/thelist")).should("have.text", "4, 6"); - - cy.get(cesc("#\\/b2") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - cy.get(cesc("#\\/thelist")).should("have.text", "4, 6"); - - cy.get(cesc("#\\/step") + " textarea").type( - "{end}{backspace}6{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/thelist")).should("have.text", "4"); - - cy.get(cesc("#\\/a2") + " textarea").type("{end}{backspace}9{enter}", { - force: true, - }); - cy.get(cesc("#\\/thelist")).should("have.text", "4"); - - cy.get(cesc("#\\/b2") + " textarea").type("{end}{backspace}41{enter}", { - force: true, - }); - cy.get(cesc("#\\/thelist")).should("have.text", "4"); - }); - - it("can override fixed property", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

From:

-

Step:

-

Fixed:

- -

- -

Change first:

-

Change second:

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/thelist")).should("have.text", "1, 3, 5, 7"); - - cy.get(cesc("#\\/a2") + " textarea").type("{end}{backspace}21{enter}", { - force: true, - }); - cy.get(cesc("#\\/thelist")).should("have.text", "21, 3, 5, 7"); - - cy.get(cesc("#\\/b2") + " textarea").type("{end}{backspace}0{enter}", { - force: true, - }); - cy.get(cesc("#\\/thelist")).should("have.text", "21, 0, 5, 7"); - - cy.get(cesc("#\\/from") + " textarea").type( - "{end}{backspace}4{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/thelist")).should("have.text", "4, 6"); - - cy.get(cesc("#\\/a2") + " textarea").type("{end}{backspace}8{enter}", { - force: true, - }); - cy.get(cesc("#\\/thelist")).should("have.text", "8, 6"); - - cy.get(cesc("#\\/b2") + " textarea").type("{end}{backspace}2{enter}", { - force: true, - }); - cy.get(cesc("#\\/thelist")).should("have.text", "8, 2"); - - cy.get(cesc("#\\/step") + " textarea").type( - "{end}{backspace}6{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/thelist")).should("have.text", "4"); - - cy.get(cesc("#\\/a2") + " textarea").type("{end}{backspace}9{enter}", { - force: true, - }); - cy.get(cesc("#\\/thelist")).should("have.text", "9"); - - cy.get(cesc("#\\/b2") + " textarea").type("{end}{backspace}41{enter}", { - force: true, - }); - cy.get(cesc("#\\/thelist")).should("have.text", "9"); - - cy.get(cesc("#\\/fx")).click(); - cy.get(cesc("#\\/step") + " textarea").type( - "{end}{backspace}1{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/thelist")).should("have.text", "4, 5, 6, 7"); - - cy.get(cesc("#\\/a2") + " textarea").type("{end}{backspace}9{enter}", { - force: true, - }); - cy.get(cesc("#\\/thelist")).should("have.text", "4, 5, 6, 7"); - - cy.get(cesc("#\\/b2") + " textarea").type("{end}{backspace}41{enter}", { - force: true, - }); - cy.get(cesc("#\\/thelist")).should("have.text", "4, 5, 6, 7"); - - cy.get(cesc("#\\/fx")).click(); - - cy.get(cesc("#\\/a2") + " textarea").type("{end}{backspace}9{enter}", { - force: true, - }); - cy.get(cesc("#\\/thelist")).should("have.text", "9, 5, 6, 7"); - - cy.get(cesc("#\\/b2") + " textarea").type("{end}{backspace}41{enter}", { - force: true, - }); - cy.get(cesc("#\\/thelist")).should("have.text", "9, 41, 6, 7"); - }); - - it('copies with link="false" are not fixed', () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

From:

-

Step:

- -

- -

Change first:

-

Change second:

- -

Copy of a2: $a2{name="a3"}

-

Copy of b2: $b2{name="b3"}

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/thelist")).should("have.text", "1, 3, 5, 7"); - cy.get(cesc(`#\\/a2`) + ` .mq-editable-field`).should("have.text", "1"); - cy.get(cesc(`#\\/b2`) + ` .mq-editable-field`).should("have.text", "3"); - cy.get(cesc("#\\/a3") + " .mjx-mrow") - .eq(0) - .should("have.text", "1"); - cy.get(cesc("#\\/b3") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - - cy.get(cesc("#\\/a2") + " textarea") - .type("{end}{backspace}21{enter}", { force: true }) - .blur(); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "21"); - cy.get(cesc("#\\/thelist")).should("have.text", "1, 3, 5, 7"); - cy.get(cesc(`#\\/a2`) + ` .mq-editable-field`).should( - "have.text", - "21", - ); - cy.get(cesc(`#\\/b2`) + ` .mq-editable-field`).should("have.text", "3"); - cy.get(cesc("#\\/a3") + " .mjx-mrow") - .eq(0) - .should("have.text", "21"); - cy.get(cesc("#\\/b3") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - - cy.get(cesc("#\\/b2") + " textarea") - .type("{end}{backspace}0{enter}", { force: true }) - .blur(); - cy.get(cesc("#\\/b3") + " .mjx-mrow").should("contain.text", "0"); - cy.get(cesc("#\\/thelist")).should("have.text", "1, 3, 5, 7"); - cy.get(cesc(`#\\/a2`) + ` .mq-editable-field`).should( - "have.text", - "21", - ); - cy.get(cesc(`#\\/b2`) + ` .mq-editable-field`).should("have.text", "0"); - cy.get(cesc("#\\/a3") + " .mjx-mrow") - .eq(0) - .should("have.text", "21"); - cy.get(cesc("#\\/b3") + " .mjx-mrow") - .eq(0) - .should("have.text", "0"); - - cy.get(cesc("#\\/from") + " textarea").type( - "{end}{backspace}4{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/thelist")).should("have.text", "4, 6"); - cy.get(cesc(`#\\/a2`) + ` .mq-editable-field`).should( - "have.text", - "21", - ); - cy.get(cesc(`#\\/b2`) + ` .mq-editable-field`).should("have.text", "0"); - cy.get(cesc("#\\/a3") + " .mjx-mrow") - .eq(0) - .should("have.text", "21"); - cy.get(cesc("#\\/b3") + " .mjx-mrow") - .eq(0) - .should("have.text", "0"); - - cy.get(cesc("#\\/a2") + " textarea") - .type("{end}{backspace}{backspace}8{enter}", { force: true }) - .blur(); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "8"); - cy.get(cesc("#\\/thelist")).should("have.text", "4, 6"); - cy.get(cesc(`#\\/a2`) + ` .mq-editable-field`).should("have.text", "8"); - cy.get(cesc(`#\\/b2`) + ` .mq-editable-field`).should("have.text", "0"); - cy.get(cesc("#\\/a3") + " .mjx-mrow") - .eq(0) - .should("have.text", "8"); - cy.get(cesc("#\\/b3") + " .mjx-mrow") - .eq(0) - .should("have.text", "0"); - - cy.get(cesc("#\\/step") + " textarea").type( - "{end}{backspace}6{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/thelist")).should("have.text", "4"); - cy.get(cesc(`#\\/a2`) + ` .mq-editable-field`).should("have.text", "8"); - cy.get(cesc(`#\\/b2`) + ` .mq-editable-field`).should("have.text", "0"); - cy.get(cesc("#\\/a3") + " .mjx-mrow") - .eq(0) - .should("have.text", "8"); - cy.get(cesc("#\\/b3") + " .mjx-mrow") - .eq(0) - .should("have.text", "0"); - - cy.get(cesc("#\\/a2") + " textarea") - .type("{end}{backspace}9{enter}", { force: true }) - .blur(); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "9"); - cy.get(cesc("#\\/thelist")).should("have.text", "4"); - cy.get(cesc(`#\\/a2`) + ` .mq-editable-field`).should("have.text", "9"); - cy.get(cesc(`#\\/b2`) + ` .mq-editable-field`).should("have.text", "0"); - cy.get(cesc("#\\/a3") + " .mjx-mrow") - .eq(0) - .should("have.text", "9"); - cy.get(cesc("#\\/b3") + " .mjx-mrow") - .eq(0) - .should("have.text", "0"); - - cy.get(cesc("#\\/b2") + " textarea") - .type("{end}{backspace}2{enter}", { force: true }) - .blur(); - cy.get(cesc("#\\/b3") + " .mjx-mrow").should("contain.text", "2"); - cy.get(cesc("#\\/thelist")).should("have.text", "4"); - cy.get(cesc(`#\\/a2`) + ` .mq-editable-field`).should("have.text", "9"); - cy.get(cesc(`#\\/b2`) + ` .mq-editable-field`).should("have.text", "2"); - cy.get(cesc("#\\/a3") + " .mjx-mrow") - .eq(0) - .should("have.text", "9"); - cy.get(cesc("#\\/b3") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - - cy.get(cesc("#\\/from") + " textarea").type( - "{end}{backspace}8{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/thelist")).should("have.text", ""); - cy.get(cesc(`#\\/a2`) + ` .mq-editable-field`).should("have.text", "9"); - cy.get(cesc(`#\\/b2`) + ` .mq-editable-field`).should("have.text", "2"); - cy.get(cesc("#\\/a3") + " .mjx-mrow") - .eq(0) - .should("have.text", "9"); - cy.get(cesc("#\\/b3") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - - cy.get(cesc("#\\/a2") + " textarea") - .type("{end}{backspace}3{enter}", { force: true }) - .blur(); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "3"); - cy.get(cesc("#\\/thelist")).should("have.text", ""); - cy.get(cesc(`#\\/a2`) + ` .mq-editable-field`).should("have.text", "3"); - cy.get(cesc(`#\\/b2`) + ` .mq-editable-field`).should("have.text", "2"); - cy.get(cesc("#\\/a3") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/b3") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - - cy.get(cesc("#\\/step") + " textarea").type( - "{end}{backspace}3{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/from") + " textarea").type( - "{end}{backspace}0{enter}", - { - force: true, - }, - ); - cy.get(cesc("#\\/thelist")).should("have.text", "0, 3, 6"); - cy.get(cesc(`#\\/a2`) + ` .mq-editable-field`).should("have.text", "3"); - cy.get(cesc(`#\\/b2`) + ` .mq-editable-field`).should("have.text", "2"); - cy.get(cesc("#\\/a3") + " .mjx-mrow") - .eq(0) - .should("have.text", "3"); - cy.get(cesc("#\\/b3") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - - cy.get(cesc("#\\/a2") + " textarea") - .type("{end}{backspace}8{enter}", { force: true }) - .blur(); - cy.get(cesc("#\\/a3") + " .mjx-mrow").should("contain.text", "8"); - cy.get(cesc("#\\/thelist")).should("have.text", "0, 3, 6"); - cy.get(cesc(`#\\/a2`) + ` .mq-editable-field`).should("have.text", "8"); - cy.get(cesc(`#\\/b2`) + ` .mq-editable-field`).should("have.text", "2"); - cy.get(cesc("#\\/a3") + " .mjx-mrow") - .eq(0) - .should("have.text", "8"); - cy.get(cesc("#\\/b3") + " .mjx-mrow") - .eq(0) - .should("have.text", "2"); - - cy.get(cesc("#\\/b2") + " textarea") - .type("{end}{backspace}7{enter}", { force: true }) - .blur(); - cy.get(cesc("#\\/b3") + " .mjx-mrow").should("contain.text", "7"); - cy.get(cesc("#\\/thelist")).should("have.text", "0, 3, 6"); - cy.get(cesc(`#\\/a2`) + ` .mq-editable-field`).should("have.text", "8"); - cy.get(cesc(`#\\/b2`) + ` .mq-editable-field`).should("have.text", "7"); - cy.get(cesc("#\\/a3") + " .mjx-mrow") - .eq(0) - .should("have.text", "8"); - cy.get(cesc("#\\/b3") + " .mjx-mrow") - .eq(0) - .should("have.text", "7"); - }); - - it("number sequence, from and to using strings with operators", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(8); - for (let i = 0; i < 8; i++) { - expect(children[i].stateValues.value).eq(-3 + i); - } - }); - }); - - it("number sequence, excludes with operators from macros", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 2 - 6 -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - let nums = [0, 1, 5, 6, 8]; - - cy.get(cesc("#\\/_p1")).should("have.text", nums.join(", ")); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let children = stateVariables["/_aslist1"].activeChildren.map( - (x) => stateVariables[x.componentName], - ); - expect(children.length).eq(nums.length); - for (let [ind, child] of children.entries()) { - expect(child.stateValues.value).eq(nums[ind]); - } - }); - }); - - it("warnings", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - - - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/nan")).should("have.text", "NaN"); - - cy.window().then(async (win) => { - let errorWarnings = await win.returnErrorWarnings1(); - - expect(errorWarnings.errors.length).eq(0); - expect(errorWarnings.warnings.length).eq(9); - - expect(errorWarnings.warnings[0].message).contain( - `Invalid length of sequence. Must be a non-negative integer`, - ); - expect(errorWarnings.warnings[0].level).eq(1); - expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(2); - expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(5); - expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(2); - expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(27); - - expect(errorWarnings.warnings[1].message).contain( - `Invalid step of sequence. Must be a number for sequence of type number`, - ); - expect(errorWarnings.warnings[1].level).eq(1); - expect(errorWarnings.warnings[1].doenetMLrange.lineBegin).eq(3); - expect(errorWarnings.warnings[1].doenetMLrange.charBegin).eq(5); - expect(errorWarnings.warnings[1].doenetMLrange.lineEnd).eq(3); - expect(errorWarnings.warnings[1].doenetMLrange.charEnd).eq(24); - - expect(errorWarnings.warnings[2].message).contain( - `Invalid step of sequence. Must be a number for sequence of type letters`, - ); - expect(errorWarnings.warnings[2].level).eq(1); - expect(errorWarnings.warnings[2].doenetMLrange.lineBegin).eq(4); - expect(errorWarnings.warnings[2].doenetMLrange.charBegin).eq(5); - expect(errorWarnings.warnings[2].doenetMLrange.lineEnd).eq(4); - expect(errorWarnings.warnings[2].doenetMLrange.charEnd).eq(40); - - expect(errorWarnings.warnings[3].message).contain( - `Invalid "from" of number sequence. Must be a number`, - ); - expect(errorWarnings.warnings[3].level).eq(1); - expect(errorWarnings.warnings[3].doenetMLrange.lineBegin).eq(5); - expect(errorWarnings.warnings[3].doenetMLrange.charBegin).eq(5); - expect(errorWarnings.warnings[3].doenetMLrange.lineEnd).eq(5); - expect(errorWarnings.warnings[3].doenetMLrange.charEnd).eq(25); - - expect(errorWarnings.warnings[4].message).contain( - `Invalid "from" of letters sequence. Must be a letter combination`, - ); - expect(errorWarnings.warnings[4].level).eq(1); - expect(errorWarnings.warnings[4].doenetMLrange.lineBegin).eq(6); - expect(errorWarnings.warnings[4].doenetMLrange.charBegin).eq(5); - expect(errorWarnings.warnings[4].doenetMLrange.lineEnd).eq(6); - expect(errorWarnings.warnings[4].doenetMLrange.charEnd).eq(40); - - expect(errorWarnings.warnings[5].message).contain( - `Invalid "from" of sequence`, - ); - expect(errorWarnings.warnings[5].level).eq(1); - expect(errorWarnings.warnings[5].doenetMLrange.lineBegin).eq(7); - expect(errorWarnings.warnings[5].doenetMLrange.charBegin).eq(5); - expect(errorWarnings.warnings[5].doenetMLrange.lineEnd).eq(7); - expect(errorWarnings.warnings[5].doenetMLrange.charEnd).eq(40); - - expect(errorWarnings.warnings[6].message).contain( - `Invalid "to" of number sequence. Must be a number.`, - ); - expect(errorWarnings.warnings[6].level).eq(1); - expect(errorWarnings.warnings[6].doenetMLrange.lineBegin).eq(8); - expect(errorWarnings.warnings[6].doenetMLrange.charBegin).eq(5); - expect(errorWarnings.warnings[6].doenetMLrange.lineEnd).eq(8); - expect(errorWarnings.warnings[6].doenetMLrange.charEnd).eq(23); - - expect(errorWarnings.warnings[7].message).contain( - `Invalid "to" of letters sequence. Must be a letter combination`, - ); - expect(errorWarnings.warnings[7].level).eq(1); - expect(errorWarnings.warnings[7].doenetMLrange.lineBegin).eq(9); - expect(errorWarnings.warnings[7].doenetMLrange.charBegin).eq(5); - expect(errorWarnings.warnings[7].doenetMLrange.lineEnd).eq(9); - expect(errorWarnings.warnings[7].doenetMLrange.charEnd).eq(38); - - expect(errorWarnings.warnings[8].message).contain( - `Invalid "to" of sequence`, - ); - expect(errorWarnings.warnings[8].level).eq(1); - expect(errorWarnings.warnings[8].doenetMLrange.lineBegin).eq(10); - expect(errorWarnings.warnings[8].doenetMLrange.charBegin).eq(5); - expect(errorWarnings.warnings[8].doenetMLrange.lineEnd).eq(10); - expect(errorWarnings.warnings[8].doenetMLrange.charEnd).eq(38); - }); - }); - - it("sequence displays as list by default", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

-

-

-

$default

-

$nocommas

-

$withcommas

-

$default{asList="false"}

-

$withcommas{asList="false"}

-

$nocommas{asList="true"}

-

-

-

-

-

-

-

-

-

- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/default")).should( - "have.text", - "1, 2, 3, 4, 5, 6, 7, 8, 9, 10", - ); - cy.get(cesc2("#/pdefault2")).should( - "have.text", - "1, 2, 3, 4, 5, 6, 7, 8, 9, 10", - ); - cy.get(cesc2("#/pdefault4")).should( - "have.text", - "1, 2, 3, 4, 5, 6, 7, 8, 9, 10", - ); - cy.get(cesc2("#/pdefault5")).should( - "have.text", - "1, 2, 3, 4, 5, 6, 7, 8, 9, 10", - ); - - cy.get(cesc2("#/nocommas")).should("have.text", "12345678910"); - cy.get(cesc2("#/pnocommas2")).should("have.text", "12345678910"); - cy.get(cesc2("#/pnocommas3")).should("have.text", "12345678910"); - cy.get(cesc2("#/pnocommas3a")).should("have.text", "12345678910"); - cy.get(cesc2("#/pnocommas4")).should("have.text", "12345678910"); - cy.get(cesc2("#/pnocommas5")).should("have.text", "12345678910"); - cy.get(cesc2("#/pnocommas6")).should("have.text", "12345678910"); - cy.get(cesc2("#/pnocommas6a")).should("have.text", "12345678910"); - - cy.get(cesc2("#/withcommas")).should( - "have.text", - "1, 2, 3, 4, 5, 6, 7, 8, 9, 10", - ); - cy.get(cesc2("#/pwithcommas2")).should( - "have.text", - "1, 2, 3, 4, 5, 6, 7, 8, 9, 10", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/pdefault"].stateValues.text).eq( - "1, 2, 3, 4, 5, 6, 7, 8, 9, 10", - ); - expect(stateVariables["/pdefault2"].stateValues.text).eq( - "1, 2, 3, 4, 5, 6, 7, 8, 9, 10", - ); - expect(stateVariables["/pdefault4"].stateValues.text).eq( - "1, 2, 3, 4, 5, 6, 7, 8, 9, 10", - ); - expect(stateVariables["/pdefault5"].stateValues.text).eq( - "1, 2, 3, 4, 5, 6, 7, 8, 9, 10", - ); - expect(stateVariables["/pnocommas"].stateValues.text).eq( - "12345678910", - ); - expect(stateVariables["/pnocommas2"].stateValues.text).eq( - "12345678910", - ); - expect(stateVariables["/pnocommas3"].stateValues.text).eq( - "12345678910", - ); - expect(stateVariables["/pnocommas3a"].stateValues.text).eq( - "12345678910", - ); - expect(stateVariables["/pnocommas4"].stateValues.text).eq( - "12345678910", - ); - expect(stateVariables["/pnocommas5"].stateValues.text).eq( - "12345678910", - ); - expect(stateVariables["/pnocommas6"].stateValues.text).eq( - "12345678910", - ); - expect(stateVariables["/pnocommas6a"].stateValues.text).eq( - "12345678910", - ); - expect(stateVariables["/pwithcommas"].stateValues.text).eq( - "1, 2, 3, 4, 5, 6, 7, 8, 9, 10", - ); - expect(stateVariables["/pwithcommas2"].stateValues.text).eq( - "1, 2, 3, 4, 5, 6, 7, 8, 9, 10", - ); - expect(stateVariables["/pwithcommas3"].stateValues.text).eq( - "1, 2, 3, 4, 5, 6, 7, 8, 9, 10", - ); - expect(stateVariables["/pwithcommas4"].stateValues.text).eq( - "1, 2, 3, 4, 5, 6, 7, 8, 9, 10", - ); - expect(stateVariables["/pwithcommas5"].stateValues.text).eq( - "1, 2, 3, 4, 5, 6, 7, 8, 9, 10", - ); - expect(stateVariables["/pwithcommas6"].stateValues.text).eq( - "1, 2, 3, 4, 5, 6, 7, 8, 9, 10", - ); - }); - }); - - it("rounding", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

-

-

-

- -

$n1a $n1b $n1c

-

$n2a $n2b $n2c

-

$n3a $n3b $n3c

-

$n4a $n4b $n4c

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let na = 10.12345; - let nb = na + 0.03257; - let nc = nb + 0.03257; - - cy.get(cesc("#\\/n1a")).should( - "have.text", - String(Math.round(na * 10 ** 8) / 10 ** 8), - ); - cy.get(cesc("#\\/n1b")).should( - "have.text", - String(Math.round(nb * 10 ** 8) / 10 ** 8), - ); - cy.get(cesc("#\\/n1c")).should( - "have.text", - String(Math.round(nc * 10 ** 8) / 10 ** 8), - ); - cy.get(cesc("#\\/n2a")).should( - "have.text", - String(Math.round(na * 10 ** 1) / 10 ** 1), - ); - cy.get(cesc("#\\/n2b")).should( - "have.text", - String(Math.round(nb * 10 ** 1) / 10 ** 1), - ); - cy.get(cesc("#\\/n2c")).should( - "have.text", - String(Math.round(nc * 10 ** 1) / 10 ** 1), - ); - cy.get(cesc("#\\/n3a")).should( - "have.text", - String(Math.round(na * 10 ** 3) / 10 ** 3), - ); - cy.get(cesc("#\\/n3b")).should( - "have.text", - String(Math.round(nb * 10 ** 3) / 10 ** 3), - ); - cy.get(cesc("#\\/n3c")).should( - "have.text", - String(Math.round(nc * 10 ** 3) / 10 ** 3), - ); - cy.get(cesc("#\\/n4a")).should("have.text", "10.0"); - cy.get(cesc("#\\/n4b")).should("have.text", "11.0"); - cy.get(cesc("#\\/n4c")).should("have.text", "12.0"); - - cy.get(cesc("#\\/n1a1")).should( - "have.text", - String(Math.round(na * 10 ** 8) / 10 ** 8), - ); - cy.get(cesc("#\\/n1b1")).should( - "have.text", - String(Math.round(nb * 10 ** 8) / 10 ** 8), - ); - cy.get(cesc("#\\/n1c1")).should( - "have.text", - String(Math.round(nc * 10 ** 8) / 10 ** 8), - ); - cy.get(cesc("#\\/n2a1")).should( - "have.text", - String(Math.round(na * 10 ** 1) / 10 ** 1), - ); - cy.get(cesc("#\\/n2b1")).should( - "have.text", - String(Math.round(nb * 10 ** 1) / 10 ** 1), - ); - cy.get(cesc("#\\/n2c1")).should( - "have.text", - String(Math.round(nc * 10 ** 1) / 10 ** 1), - ); - cy.get(cesc("#\\/n3a1")).should( - "have.text", - String(Math.round(na * 10 ** 3) / 10 ** 3), - ); - cy.get(cesc("#\\/n3b1")).should( - "have.text", - String(Math.round(nb * 10 ** 3) / 10 ** 3), - ); - cy.get(cesc("#\\/n3c1")).should( - "have.text", - String(Math.round(nc * 10 ** 3) / 10 ** 3), - ); - cy.get(cesc("#\\/n4a1")).should("have.text", "10.0"); - cy.get(cesc("#\\/n4b1")).should("have.text", "11.0"); - cy.get(cesc("#\\/n4c1")).should("have.text", "12.0"); - }); -}); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/shuffle.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/shuffle.cy.js deleted file mode 100644 index b7aa7dd6a..000000000 --- a/packages/test-cypress/cypress/e2e/tagSpecific/shuffle.cy.js +++ /dev/null @@ -1,652 +0,0 @@ -import { cesc } from "@doenet/utils"; - -describe("Shuffle Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("consistent order for n elements for given variant", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

m:

-

n:

-

- -

-

$sh

-

$_aslist1

- `, - requestedVariantIndex: 1, - }, - "*", - ); - }); - - cy.get(cesc("#\\/n2")).should("have.text", "6"); - - let texts = {}; - let orders = {}; - - cy.window().then(async (win) => { - let m = 1, - n = 6; - - let stateVariables = await win.returnAllStateVariables1(); - let componentOrder = - stateVariables["/sh"].stateValues.componentOrder; - - expect([...componentOrder].sort((a, b) => a - b)).eqls( - [...Array(n - m + 1).keys()].map((x) => x + m), - ); - - orders[[m, n]] = componentOrder; - - let pText = componentOrder.map((x) => x + m - 1).join(", "); - - cy.get(cesc("#\\/pList")).should("have.text", pText); - cy.get(cesc("#\\/pList2")).should("have.text", pText); - cy.get(cesc("#\\/pList3")).should("have.text", pText); - - texts[[m, n]] = pText; - }); - - cy.log("switch n to 8"); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}8{enter}", { - force: true, - }); - cy.get(cesc("#\\/n2")).should("have.text", "8"); - - cy.window().then(async (win) => { - let m = 1, - n = 8; - - let stateVariables = await win.returnAllStateVariables1(); - let componentOrder = - stateVariables["/sh"].stateValues.componentOrder; - - expect([...componentOrder].sort((a, b) => a - b)).eqls( - [...Array(n - m + 1).keys()].map((x) => x + m), - ); - - orders[[m, n]] = componentOrder; - - let pText = componentOrder.map((x) => x + m - 1).join(", "); - - cy.get(cesc("#\\/pList")).should("have.text", pText); - cy.get(cesc("#\\/pList2")).should("have.text", pText); - cy.get(cesc("#\\/pList3")).should("have.text", pText); - - texts[[m, n]] = pText; - }); - - cy.log("get another list of length 6 by setting m to 3"); - - cy.get(cesc("#\\/m") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - cy.get(cesc("#\\/m2")).should("have.text", "3"); - - cy.window().then(async (win) => { - let m = 3, - n = 8; - - let stateVariables = await win.returnAllStateVariables1(); - let componentOrder = - stateVariables["/sh"].stateValues.componentOrder; - - expect(componentOrder).eqls(orders[[1, 6]]); - - orders[[m, n]] = componentOrder; - - let pText = componentOrder.map((x) => x + m - 1).join(", "); - - cy.get(cesc("#\\/pList")).should("have.text", pText); - cy.get(cesc("#\\/pList2")).should("have.text", pText); - cy.get(cesc("#\\/pList3")).should("have.text", pText); - - texts[[m, n]] = pText; - }); - - cy.log("get another list of length 8 by setting n to 10"); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}10{enter}", { - force: true, - }); - cy.get(cesc("#\\/n2")).should("have.text", "10"); - - cy.window().then(async (win) => { - let m = 3, - n = 10; - - let stateVariables = await win.returnAllStateVariables1(); - let componentOrder = - stateVariables["/sh"].stateValues.componentOrder; - - expect(componentOrder).eqls(orders[[1, 8]]); - - orders[[m, n]] = componentOrder; - - let pText = componentOrder.map((x) => x + m - 1).join(", "); - - cy.get(cesc("#\\/pList")).should("have.text", pText); - cy.get(cesc("#\\/pList2")).should("have.text", pText); - cy.get(cesc("#\\/pList3")).should("have.text", pText); - - texts[[m, n]] = pText; - }); - - cy.log("values change with another variant"); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

m:

-

n:

-

- -

-

$sh

-

$_aslist1

- `, - requestedVariantIndex: 2, - }, - "*", - ); - }); - - cy.get(cesc("#\\/m2")).should("have.text", "1"); - cy.get(cesc("#\\/n2")).should("have.text", "6"); - - cy.window().then(async (win) => { - let m = 1, - n = 6; - - let stateVariables = await win.returnAllStateVariables1(); - let componentOrder = - stateVariables["/sh"].stateValues.componentOrder; - - expect(componentOrder).not.eqls(orders[[m, n]]); - - expect([...componentOrder].sort((a, b) => a - b)).eqls( - [...Array(n - m + 1).keys()].map((x) => x + m), - ); - - orders[[m, n]] = componentOrder; - - let pText = componentOrder.map((x) => x + m - 1).join(", "); - - cy.get(cesc("#\\/pList")).should("have.text", pText); - cy.get(cesc("#\\/pList2")).should("have.text", pText); - cy.get(cesc("#\\/pList3")).should("have.text", pText); - - texts[[m, n]] = pText; - }); - - cy.log("switch n to 8"); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}8{enter}", { - force: true, - }); - cy.get(cesc("#\\/n2")).should("have.text", "8"); - - cy.window().then(async (win) => { - let m = 1, - n = 8; - - let stateVariables = await win.returnAllStateVariables1(); - let componentOrder = - stateVariables["/sh"].stateValues.componentOrder; - - expect(componentOrder).not.eqls(orders[[m, n]]); - - expect([...componentOrder].sort((a, b) => a - b)).eqls( - [...Array(n - m + 1).keys()].map((x) => x + m), - ); - - orders[[m, n]] = componentOrder; - - let pText = componentOrder.map((x) => x + m - 1).join(", "); - - cy.get(cesc("#\\/pList")).should("have.text", pText); - cy.get(cesc("#\\/pList2")).should("have.text", pText); - cy.get(cesc("#\\/pList3")).should("have.text", pText); - - texts[[m, n]] = pText; - }); - - cy.log("get another list of length 6 by setting m to 3"); - - cy.get(cesc("#\\/m") + " textarea").type("{end}{backspace}3{enter}", { - force: true, - }); - cy.get(cesc("#\\/m2")).should("have.text", "3"); - - cy.window().then(async (win) => { - let m = 3, - n = 8; - - let stateVariables = await win.returnAllStateVariables1(); - let componentOrder = - stateVariables["/sh"].stateValues.componentOrder; - - expect(componentOrder).eqls(orders[[1, 6]]); - - orders[[m, n]] = componentOrder; - - let pText = componentOrder.map((x) => x + m - 1).join(", "); - - cy.get(cesc("#\\/pList")).should("have.text", pText); - cy.get(cesc("#\\/pList2")).should("have.text", pText); - cy.get(cesc("#\\/pList3")).should("have.text", pText); - - texts[[m, n]] = pText; - }); - - cy.log("get another list of length 8 by setting n to 10"); - - cy.get(cesc("#\\/n") + " textarea").type("{end}{backspace}10{enter}", { - force: true, - }); - cy.get(cesc("#\\/n2")).should("have.text", "10"); - - cy.window().then(async (win) => { - let m = 3, - n = 10; - - let stateVariables = await win.returnAllStateVariables1(); - let componentOrder = - stateVariables["/sh"].stateValues.componentOrder; - - expect(componentOrder).eqls(orders[[1, 8]]); - - orders[[m, n]] = componentOrder; - - let pText = componentOrder.map((x) => x + m - 1).join(", "); - - cy.get(cesc("#\\/pList")).should("have.text", pText); - cy.get(cesc("#\\/pList2")).should("have.text", pText); - cy.get(cesc("#\\/pList3")).should("have.text", pText); - - texts[[m, n]] = pText; - }); - }); - - it("shuffle with math and mathlists", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- x - y - z - a b c d - q - 1 2 3 4 -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let options = [ - "x", - "y", - "z", - "a", - "b", - "c", - "d", - "q", - "1", - "2", - "3", - "4", - ]; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let componentOrder = - stateVariables["/sh"].stateValues.componentOrder; - - expect([...componentOrder].sort((a, b) => a - b)).eqls( - [...Array(12).keys()].map((x) => x + 1), - ); - - let orderedOptions = componentOrder.map((x) => options[x - 1]); - - let indOfa = orderedOptions.indexOf("a"); - let indOfb = orderedOptions.indexOf("b"); - let indOfc = orderedOptions.indexOf("c"); - let indOfd = orderedOptions.indexOf("d"); - - expect([indOfb, indOfc, indOfd]).not.eqls([ - indOfa + 1, - indOfa + 2, - indOfa + 3, - ]); - - let indOf1 = orderedOptions.indexOf("1"); - let indOf2 = orderedOptions.indexOf("2"); - let indOf3 = orderedOptions.indexOf("3"); - let indOf4 = orderedOptions.indexOf("4"); - - expect([indOf2, indOf3, indOf4]).not.eqls([ - indOf1 + 1, - indOf1 + 2, - indOf1 + 3, - ]); - - for (let ind = 0; ind < 12; ind++) { - cy.get(cesc("#\\/pList") + " .mjx-mrow") - .eq(ind) - .should("contain.text", orderedOptions[ind]); - } - }); - }); - - it("shuffle with number and numberlists", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- 10 - 11 - 12 - 101 102 103 104 105 - -5 - 1 2 3 4 - -99 -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let options = [ - "10", - "11", - "12", - "101", - "102", - "103", - "104", - "105", - "-5", - "1", - "2", - "3", - "4", - "-99", - ]; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let componentOrder = - stateVariables["/sh"].stateValues.componentOrder; - - expect([...componentOrder].sort((a, b) => a - b)).eqls( - [...Array(14).keys()].map((x) => x + 1), - ); - - let orderedOptions = componentOrder.map((x) => options[x - 1]); - - let indOf1 = orderedOptions.indexOf("1"); - let indOf2 = orderedOptions.indexOf("2"); - let indOf3 = orderedOptions.indexOf("3"); - let indOf4 = orderedOptions.indexOf("4"); - - expect([indOf2, indOf3, indOf4]).not.eqls([ - indOf1 + 1, - indOf1 + 2, - indOf1 + 3, - ]); - - let indOf101 = orderedOptions.indexOf("101"); - let indOf102 = orderedOptions.indexOf("102"); - let indOf103 = orderedOptions.indexOf("103"); - let indOf104 = orderedOptions.indexOf("104"); - let indOf105 = orderedOptions.indexOf("105"); - - expect([indOf102, indOf103, indOf104, indOf105]).not.eqls([ - indOf101 + 1, - indOf101 + 2, - indOf101 + 3, - indOf101 + 4, - ]); - - cy.get(cesc("#\\/pList")).should( - "have.text", - orderedOptions.join(", "), - ); - }); - }); - - it("shuffle with text and textlists", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- apple - banana - orange - hello there now then too - almost - 1 2 3 4 - above -

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let options = [ - "apple", - "banana", - "orange", - "hello", - "there", - "now", - "then", - "too", - "almost", - "1", - "2", - "3", - "4", - "above", - ]; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let componentOrder = - stateVariables["/sh"].stateValues.componentOrder; - - expect([...componentOrder].sort((a, b) => a - b)).eqls( - [...Array(14).keys()].map((x) => x + 1), - ); - - let orderedOptions = componentOrder.map((x) => options[x - 1]); - - let indOf1 = orderedOptions.indexOf("1"); - let indOf2 = orderedOptions.indexOf("2"); - let indOf3 = orderedOptions.indexOf("3"); - let indOf4 = orderedOptions.indexOf("4"); - - expect([indOf2, indOf3, indOf4]).not.eqls([ - indOf1 + 1, - indOf1 + 2, - indOf1 + 3, - ]); - - let indOfhello = orderedOptions.indexOf("hello"); - let indOfthere = orderedOptions.indexOf("there"); - let indOfnow = orderedOptions.indexOf("now"); - let indOfthen = orderedOptions.indexOf("then"); - let indOftoo = orderedOptions.indexOf("too"); - - expect([indOfthere, indOfnow, indOfthen, indOftoo]).not.eqls([ - indOfhello + 1, - indOfhello + 2, - indOfhello + 3, - indOfhello + 4, - ]); - - cy.get(cesc("#\\/pList")).should( - "have.text", - orderedOptions.join(", "), - ); - }); - }); - - it("shuffle sugar type math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- a b c x y z -

-

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let options = ["a", "b", "c", "x", "y", "z"]; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let componentOrder = - stateVariables["/sh"].stateValues.componentOrder; - - expect([...componentOrder].sort((a, b) => a - b)).eqls( - [...Array(6).keys()].map((x) => x + 1), - ); - - let orderedOptions = componentOrder.map( - (x) => options[x - 1] + options[x - 1] + options[x - 1], - ); - - cy.get(cesc("#\\/pList")).should( - "have.text", - orderedOptions.join(", "), - ); - cy.get(cesc("#\\/pNoList")).should( - "have.text", - orderedOptions.join(""), - ); - }); - }); - - it("shuffle sugar type number", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- 101 542 817 527 51 234 801 -

-

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let options = [101, 542, 817, 527, 51, 234, 801]; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let componentOrder = - stateVariables["/sh"].stateValues.componentOrder; - - expect([...componentOrder].sort((a, b) => a - b)).eqls( - [...Array(7).keys()].map((x) => x + 1), - ); - - let orderedOptions = componentOrder.map((x) => options[x - 1]); - - cy.get(cesc("#\\/pList")).should( - "have.text", - orderedOptions.join(", "), - ); - cy.get(cesc("#\\/pNoList")).should( - "have.text", - orderedOptions.join(""), - ); - }); - }); - - it("shuffle sugar type text", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- apple - banana - orange - almost - above -

-

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let options = ["apple", "banana", "orange", "almost", "above"]; - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let componentOrder = - stateVariables["/sh"].stateValues.componentOrder; - - expect([...componentOrder].sort((a, b) => a - b)).eqls( - [...Array(5).keys()].map((x) => x + 1), - ); - - let orderedOptions = componentOrder.map((x) => options[x - 1]); - - cy.get(cesc("#\\/pList")).should( - "have.text", - orderedOptions.join(", "), - ); - cy.get(cesc("#\\/pNoList")).should( - "have.text", - orderedOptions.join(""), - ); - }); - }); -}); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/sort.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/sort.cy.js deleted file mode 100644 index 782b7de18..000000000 --- a/packages/test-cypress/cypress/e2e/tagSpecific/sort.cy.js +++ /dev/null @@ -1,1791 +0,0 @@ -import { cesc } from "@doenet/utils"; - -describe("Sort Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("sort numbers and math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - 3 - pi - 1 - e - sqrt(2) - sqrt(3) - -3 10 2 - log(2) 1/e sin(2) -2/3 - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/x1")).should("have.text", "-3"); - cy.get(cesc("#\\/x2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−23"); - }); - cy.get(cesc("#\\/x3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1e"); - }); - cy.get(cesc("#\\/x4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("log(2)"); - }); - cy.get(cesc("#\\/x5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(2)"); - }); - cy.get(cesc("#\\/x6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/x7")).should("have.text", "1.4142"); - cy.get(cesc("#\\/x8")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("√3"); - }); - cy.get(cesc("#\\/x9")).should("have.text", "2"); - cy.get(cesc("#\\/x10")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("e"); - }); - cy.get(cesc("#\\/x11")).should("have.text", "3"); - - cy.get(cesc("#\\/x12")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("π"); - }); - cy.get(cesc("#\\/x13")).should("have.text", "10"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/x1"].stateValues.value).eq(-3); - expect(stateVariables["/x2"].stateValues.value).eqls([ - "-", - ["/", 2, 3], - ]); - expect(stateVariables["/x3"].stateValues.value).eqls(["/", 1, "e"]); - expect(stateVariables["/x4"].stateValues.value).eqls([ - "apply", - "log", - 2, - ]); - expect(stateVariables["/x5"].stateValues.value).eqls([ - "apply", - "sin", - 2, - ]); - expect(stateVariables["/x6"].stateValues.value).eqls(1); - expect(stateVariables["/x7"].stateValues.value).closeTo( - Math.sqrt(2), - 1e-14, - ); - expect(stateVariables["/x8"].stateValues.value).eqls([ - "apply", - "sqrt", - 3, - ]); - expect(stateVariables["/x9"].stateValues.value).eq(2); - expect(stateVariables["/x10"].stateValues.value).eqls("e"); - expect(stateVariables["/x11"].stateValues.value).eq(3); - expect(stateVariables["/x12"].stateValues.value).eqls("pi"); - expect(stateVariables["/x13"].stateValues.value).eq(10); - }); - }); - - it("sort dynamic maths", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Values to sort: - - - - -

- - - $m1$m2$m3 - $m4 - 70 - -pi - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/x1")).should("have.text", "-∞"); - cy.get(cesc("#\\/x2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−π"); - }); - cy.get(cesc("#\\/x3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("56"); - }); - cy.get(cesc("#\\/x4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("√2"); - }); - cy.get(cesc("#\\/x5")).should("have.text", "70"); - cy.get(cesc("#\\/x6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("∞"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/x1"].stateValues.value).eq(-Infinity); - expect(stateVariables["/x2"].stateValues.value).eqls(["-", "pi"]); - expect(stateVariables["/x3"].stateValues.value).eqls(["/", 5, 6]); - expect(stateVariables["/x4"].stateValues.value).eqls([ - "apply", - "sqrt", - 2, - ]); - expect(stateVariables["/x5"].stateValues.value).eq(70); - expect(stateVariables["/x6"].stateValues.value).eqls(Infinity); - }); - - cy.log("change first value"); - cy.get(cesc("#\\/m1") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}-5{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/x2")).should("contain.text", "−5"); - - cy.get(cesc("#\\/x1")).should("have.text", "-∞"); - cy.get(cesc("#\\/x2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−5"); - }); - cy.get(cesc("#\\/x3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−π"); - }); - cy.get(cesc("#\\/x4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("56"); - }); - cy.get(cesc("#\\/x5")).should("have.text", "70"); - - cy.get(cesc("#\\/x6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("∞"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/x1"].stateValues.value).eq(-Infinity); - expect(stateVariables["/x2"].stateValues.value).eqls(-5); - expect(stateVariables["/x3"].stateValues.value).eqls(["-", "pi"]); - expect(stateVariables["/x4"].stateValues.value).eqls(["/", 5, 6]); - expect(stateVariables["/x5"].stateValues.value).eq(70); - expect(stateVariables["/x6"].stateValues.value).eqls(Infinity); - }); - - cy.log("change second value"); - cy.get(cesc("#\\/m2") + " textarea").type( - "{ctrl+home}{shift+end}{backspace}e^5{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/x4")).should("have.text", "70"); - cy.get(cesc("#\\/x1")).should("have.text", "-∞"); - cy.get(cesc("#\\/x2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−5"); - }); - cy.get(cesc("#\\/x3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−π"); - }); - cy.get(cesc("#\\/x5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("e5"); - }); - cy.get(cesc("#\\/x6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("∞"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/x1"].stateValues.value).eq(-Infinity); - expect(stateVariables["/x2"].stateValues.value).eqls(-5); - expect(stateVariables["/x3"].stateValues.value).eqls(["-", "pi"]); - expect(stateVariables["/x4"].stateValues.value).eq(70); - expect(stateVariables["/x5"].stateValues.value).eqls(["^", "e", 5]); - expect(stateVariables["/x6"].stateValues.value).eqls(Infinity); - }); - - cy.log("change third value"); - cy.get(cesc("#\\/m3") + " textarea").type( - "{end}{backspace}-100{enter}", - { - force: true, - }, - ); - - cy.get(cesc("#\\/x5")).should("have.text", "70"); - cy.get(cesc("#\\/x1")).should("have.text", "-∞"); - cy.get(cesc("#\\/x2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−100"); - }); - cy.get(cesc("#\\/x3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−5"); - }); - cy.get(cesc("#\\/x4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−π"); - }); - cy.get(cesc("#\\/x6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("e5"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/x1"].stateValues.value).eq(-Infinity); - expect(stateVariables["/x2"].stateValues.value).eqls(-100); - expect(stateVariables["/x3"].stateValues.value).eqls(-5); - expect(stateVariables["/x4"].stateValues.value).eqls(["-", "pi"]); - expect(stateVariables["/x5"].stateValues.value).eq(70); - expect(stateVariables["/x6"].stateValues.value).eqls(["^", "e", 5]); - }); - - cy.log("change fourth value"); - cy.get(cesc("#\\/m4") + " textarea").type( - "{end}{backspace}{backspace}0{enter}", - { force: true }, - ); - - cy.get(cesc("#\\/x4")).should("have.text", "0"); - cy.get(cesc("#\\/x1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−100"); - }); - cy.get(cesc("#\\/x2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−5"); - }); - cy.get(cesc("#\\/x3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−π"); - }); - cy.get(cesc("#\\/x5")).should("have.text", "70"); - cy.get(cesc("#\\/x6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("e5"); - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/x1"].stateValues.value).eqls(-100); - expect(stateVariables["/x2"].stateValues.value).eqls(-5); - expect(stateVariables["/x3"].stateValues.value).eqls(["-", "pi"]); - expect(stateVariables["/x4"].stateValues.value).eq(0); - expect(stateVariables["/x5"].stateValues.value).eq(70); - expect(stateVariables["/x6"].stateValues.value).eqls(["^", "e", 5]); - }); - }); - - it("sort nested lists of numbers and math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - sqrt(2)10 - - 2 - 3 - - -3 - - - sqrt(3) 1/e - - e pi - - log(2) 1 - - sin(2) -2/3 - - - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/x1")).should("have.text", "-3"); - cy.get(cesc("#\\/x2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("−23"); - }); - cy.get(cesc("#\\/x3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1e"); - }); - cy.get(cesc("#\\/x4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("log(2)"); - }); - cy.get(cesc("#\\/x5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("sin(2)"); - }); - cy.get(cesc("#\\/x6")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("1"); - }); - cy.get(cesc("#\\/x7")).should("have.text", "1.4142"); - cy.get(cesc("#\\/x8")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("√3"); - }); - cy.get(cesc("#\\/x9")).should("have.text", "2"); - cy.get(cesc("#\\/x10")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("e"); - }); - cy.get(cesc("#\\/x11")).should("have.text", "3"); - - cy.get(cesc("#\\/x12")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("π"); - }); - cy.get(cesc("#\\/x13")).should("have.text", "10"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/x1"].stateValues.value).eq(-3); - expect(stateVariables["/x2"].stateValues.value).eqls([ - "-", - ["/", 2, 3], - ]); - expect(stateVariables["/x3"].stateValues.value).eqls(["/", 1, "e"]); - expect(stateVariables["/x4"].stateValues.value).eqls([ - "apply", - "log", - 2, - ]); - expect(stateVariables["/x5"].stateValues.value).eqls([ - "apply", - "sin", - 2, - ]); - expect(stateVariables["/x6"].stateValues.value).eqls(1); - expect(stateVariables["/x7"].stateValues.value).closeTo( - Math.sqrt(2), - 1e-14, - ); - expect(stateVariables["/x8"].stateValues.value).eqls([ - "apply", - "sqrt", - 3, - ]); - expect(stateVariables["/x9"].stateValues.value).eq(2); - expect(stateVariables["/x10"].stateValues.value).eqls("e"); - expect(stateVariables["/x11"].stateValues.value).eq(3); - expect(stateVariables["/x12"].stateValues.value).eqls("pi"); - expect(stateVariables["/x13"].stateValues.value).eq(10); - }); - }); - - it("sort points", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (0,1) - (-2,1) - (7,1) - (3,1) - (5,1) - - - $A$B$C$D$E - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/P1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−2,1)"); - }); - cy.get(cesc("#\\/P2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,1)"); - }); - cy.get(cesc("#\\/P3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,1)"); - }); - cy.get(cesc("#\\/P4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,1)"); - }); - cy.get(cesc("#\\/P5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(7,1)"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/A", - args: { x: -8, y: 9 }, - }); - }); - - cy.get(cesc("#\\/P1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−8,9)"); - }); - cy.get(cesc("#\\/P2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−2,1)"); - }); - cy.get(cesc("#\\/P3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,1)"); - }); - cy.get(cesc("#\\/P4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,1)"); - }); - cy.get(cesc("#\\/P5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(7,1)"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/B", - args: { x: 8, y: -3 }, - }); - }); - - cy.get(cesc("#\\/P1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−8,9)"); - }); - cy.get(cesc("#\\/P2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,1)"); - }); - cy.get(cesc("#\\/P3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,1)"); - }); - cy.get(cesc("#\\/P4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(7,1)"); - }); - cy.get(cesc("#\\/P5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(8,−3)"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/C", - args: { x: 4, y: 5 }, - }); - }); - - cy.get(cesc("#\\/P1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−8,9)"); - }); - cy.get(cesc("#\\/P2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,1)"); - }); - cy.get(cesc("#\\/P3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(4,5)"); - }); - cy.get(cesc("#\\/P4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,1)"); - }); - cy.get(cesc("#\\/P5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(8,−3)"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/D", - args: { x: -9, y: 0 }, - }); - }); - - cy.get(cesc("#\\/P1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−9,0)"); - }); - cy.get(cesc("#\\/P2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−8,9)"); - }); - cy.get(cesc("#\\/P3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(4,5)"); - }); - cy.get(cesc("#\\/P4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,1)"); - }); - cy.get(cesc("#\\/P5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(8,−3)"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/E", - args: { x: -2, y: -1 }, - }); - }); - - cy.get(cesc("#\\/P1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−9,0)"); - }); - cy.get(cesc("#\\/P2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−8,9)"); - }); - cy.get(cesc("#\\/P3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−2,−1)"); - }); - cy.get(cesc("#\\/P4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(4,5)"); - }); - cy.get(cesc("#\\/P5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(8,−3)"); - }); - }); - - it("sort points by component", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (0,5) - (-2,6) - (7,-3) - (3,2) - (5,1) - - - $A$B$C$D$E - $A$B$C$D$E - $A$B$C$D$E - $A$B$C$D$E - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/P1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−2,6)"); - }); - cy.get(cesc("#\\/P2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,5)"); - }); - cy.get(cesc("#\\/P3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2)"); - }); - cy.get(cesc("#\\/P4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,1)"); - }); - cy.get(cesc("#\\/P5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(7,−3)"); - }); - - cy.get(cesc("#\\/Px1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−2,6)"); - }); - cy.get(cesc("#\\/Px2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,5)"); - }); - cy.get(cesc("#\\/Px3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2)"); - }); - cy.get(cesc("#\\/Px4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,1)"); - }); - cy.get(cesc("#\\/Px5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(7,−3)"); - }); - - cy.get(cesc("#\\/Py1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(7,−3)"); - }); - cy.get(cesc("#\\/Py2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,1)"); - }); - cy.get(cesc("#\\/Py3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2)"); - }); - cy.get(cesc("#\\/Py4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,5)"); - }); - cy.get(cesc("#\\/Py5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−2,6)"); - }); - - cy.get(cesc("#\\/Pu1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,5)"); - }); - cy.get(cesc("#\\/Pu2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−2,6)"); - }); - cy.get(cesc("#\\/Pu3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(7,−3)"); - }); - cy.get(cesc("#\\/Pu4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2)"); - }); - cy.get(cesc("#\\/Pu5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,1)"); - }); - }); - - it("sort vectors", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - - $A$B$C$D$E - $A$B$C$D$E - $A$B$C$D$E - - $A$B$C$D$E - $A$B$C$D$E - $A$B$C$D$E - - $A$B$C$D$E - $A$B$C$D$E - $A$B$C$D$E - - $A$B$C$D$E - $A$B$C$D$E - $A$B$C$D$E - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/V1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−2,6)"); - }); - cy.get(cesc("#\\/V2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,5)"); - }); - cy.get(cesc("#\\/V3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2)"); - }); - cy.get(cesc("#\\/V4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,1)"); - }); - cy.get(cesc("#\\/V5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(7,−2)"); - }); - - cy.get(cesc("#\\/Vd1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−2,6)"); - }); - cy.get(cesc("#\\/Vd2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,5)"); - }); - cy.get(cesc("#\\/Vd3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2)"); - }); - cy.get(cesc("#\\/Vd4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,1)"); - }); - cy.get(cesc("#\\/Vd5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(7,−2)"); - }); - - cy.get(cesc("#\\/Vt1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(7,−2)"); - }); - cy.get(cesc("#\\/Vt2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,1)"); - }); - cy.get(cesc("#\\/Vt3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2)"); - }); - cy.get(cesc("#\\/Vt4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−2,6)"); - }); - cy.get(cesc("#\\/Vt5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,5)"); - }); - - cy.get(cesc("#\\/Vx1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−2,6)"); - }); - cy.get(cesc("#\\/Vx2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,5)"); - }); - cy.get(cesc("#\\/Vx3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2)"); - }); - cy.get(cesc("#\\/Vx4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,1)"); - }); - cy.get(cesc("#\\/Vx5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(7,−2)"); - }); - - cy.get(cesc("#\\/Vxd1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−2,6)"); - }); - cy.get(cesc("#\\/Vxd2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,5)"); - }); - cy.get(cesc("#\\/Vxd3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2)"); - }); - cy.get(cesc("#\\/Vxd4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,1)"); - }); - cy.get(cesc("#\\/Vxd5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(7,−2)"); - }); - - cy.get(cesc("#\\/Vxt1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(7,−2)"); - }); - cy.get(cesc("#\\/Vxt2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,1)"); - }); - cy.get(cesc("#\\/Vxt3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2)"); - }); - cy.get(cesc("#\\/Vxt4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−2,6)"); - }); - cy.get(cesc("#\\/Vxt5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,5)"); - }); - - cy.get(cesc("#\\/Vy1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(7,−2)"); - }); - cy.get(cesc("#\\/Vy2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,1)"); - }); - cy.get(cesc("#\\/Vy3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2)"); - }); - cy.get(cesc("#\\/Vy4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,5)"); - }); - cy.get(cesc("#\\/Vy5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−2,6)"); - }); - - cy.get(cesc("#\\/Vyd1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(7,−2)"); - }); - cy.get(cesc("#\\/Vyd2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,1)"); - }); - cy.get(cesc("#\\/Vyd3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2)"); - }); - cy.get(cesc("#\\/Vyd4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,5)"); - }); - cy.get(cesc("#\\/Vyd5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−2,6)"); - }); - - cy.get(cesc("#\\/Vyt1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,1)"); - }); - cy.get(cesc("#\\/Vyt2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,5)"); - }); - cy.get(cesc("#\\/Vyt3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(7,−2)"); - }); - cy.get(cesc("#\\/Vyt4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2)"); - }); - cy.get(cesc("#\\/Vyt5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−2,6)"); - }); - - cy.get(cesc("#\\/Vu1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,5)"); - }); - cy.get(cesc("#\\/Vu2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−2,6)"); - }); - cy.get(cesc("#\\/Vu3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(7,−2)"); - }); - cy.get(cesc("#\\/Vu4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2)"); - }); - cy.get(cesc("#\\/Vu5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,1)"); - }); - - cy.get(cesc("#\\/Vud1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,5)"); - }); - cy.get(cesc("#\\/Vud2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−2,6)"); - }); - cy.get(cesc("#\\/Vud3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(7,−2)"); - }); - cy.get(cesc("#\\/Vud4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2)"); - }); - cy.get(cesc("#\\/Vud5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,1)"); - }); - - cy.get(cesc("#\\/Vut1")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(0,5)"); - }); - cy.get(cesc("#\\/Vut2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(−2,6)"); - }); - cy.get(cesc("#\\/Vut3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(7,−2)"); - }); - cy.get(cesc("#\\/Vut4")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2)"); - }); - cy.get(cesc("#\\/Vut5")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(5,1)"); - }); - }); - - it("sort by prop", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

Coords for last point:

- - (a,b) - x - - - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/P1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/P2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("\uff3f"); - }); - cy.get(cesc("#\\/P3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(a,b)"); - }); - cy.get(cesc("#\\/P4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(x,y,z)"); - }); - cy.get(cesc("#\\/P5") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(s,t,u,v)"); - }); - - cy.get(cesc("#\\/cs") + " textarea").type("(a,b,c,d){enter}", { - force: true, - }); - - cy.get(cesc("#\\/P5") + " .mjx-mrow").should( - "contain.text", - "(a,b,c,d)", - ); - - cy.get(cesc("#\\/P1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/P2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(a,b)"); - }); - cy.get(cesc("#\\/P3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(x,y,z)"); - }); - cy.get(cesc("#\\/P4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(s,t,u,v)"); - }); - cy.get(cesc("#\\/P5") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(a,b,c,d)"); - }); - - cy.get(cesc("#\\/cs") + " textarea").type( - "{ctrl+home}{shift+ctrl+end}{backspace}(3,4,5){enter}", - { force: true }, - ); - - cy.get(cesc("#\\/P4") + " .mjx-mrow").should("contain.text", "(3,4,5)"); - - cy.get(cesc("#\\/P1") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/P2") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(a,b)"); - }); - cy.get(cesc("#\\/P3") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(x,y,z)"); - }); - cy.get(cesc("#\\/P4") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,4,5)"); - }); - cy.get(cesc("#\\/P5") + " .mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(s,t,u,v)"); - }); - }); - - it("sort texts", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - banana - apple - pear - grape cherry kiwi - strawberry - mango - passion fruit - orange boysenberry fig currant - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/x1")).should("have.text", "apple"); - cy.get(cesc("#\\/x2")).should("have.text", "banana"); - cy.get(cesc("#\\/x3")).should("have.text", "boysenberry"); - cy.get(cesc("#\\/x4")).should("have.text", "cherry"); - cy.get(cesc("#\\/x5")).should("have.text", "currant"); - cy.get(cesc("#\\/x6")).should("have.text", "fig"); - cy.get(cesc("#\\/x7")).should("have.text", "grape"); - cy.get(cesc("#\\/x8")).should("have.text", "kiwi"); - cy.get(cesc("#\\/x9")).should("have.text", "mango"); - cy.get(cesc("#\\/x10")).should("have.text", "orange"); - cy.get(cesc("#\\/x11")).should("have.text", "passion fruit"); - cy.get(cesc("#\\/x12")).should("have.text", "pear"); - cy.get(cesc("#\\/x13")).should("have.text", "strawberry"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/x1"].stateValues.value).eq("apple"); - expect(stateVariables["/x2"].stateValues.value).eq("banana"); - expect(stateVariables["/x3"].stateValues.value).eq("boysenberry"); - expect(stateVariables["/x4"].stateValues.value).eq("cherry"); - expect(stateVariables["/x5"].stateValues.value).eq("currant"); - expect(stateVariables["/x6"].stateValues.value).eq("fig"); - expect(stateVariables["/x7"].stateValues.value).eq("grape"); - expect(stateVariables["/x8"].stateValues.value).eq("kiwi"); - expect(stateVariables["/x9"].stateValues.value).eq("mango"); - expect(stateVariables["/x10"].stateValues.value).eq("orange"); - expect(stateVariables["/x11"].stateValues.value).eq( - "passion fruit", - ); - expect(stateVariables["/x12"].stateValues.value).eq("pear"); - expect(stateVariables["/x13"].stateValues.value).eq("strawberry"); - }); - }); - - it("sort text, numbers, maths", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - b - 3 - 5 - 1 z 15 orange - x - 222 - 8 u - 99 765 - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait for page to load - - cy.get(cesc("#\\/x1")).should("have.text", "1"); - cy.get(cesc("#\\/x2")).should("have.text", "15"); - cy.get(cesc("#\\/x3")).should("have.text", "222"); - cy.get(cesc("#\\/x4")).should("have.text", "3"); - cy.get(cesc("#\\/x5") + " .mjx-mrow") - .eq(0) - .should("have.text", "5"); - cy.get(cesc("#\\/x6")).should("have.text", "765"); - cy.get(cesc("#\\/x7") + " .mjx-mrow") - .eq(0) - .should("have.text", "8"); - cy.get(cesc("#\\/x8")).should("have.text", "99"); - cy.get(cesc("#\\/x9")).should("have.text", "b"); - cy.get(cesc("#\\/x10")).should("have.text", "orange"); - cy.get(cesc("#\\/x11") + " .mjx-mrow") - .eq(0) - .should("have.text", "u"); - cy.get(cesc("#\\/x12") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - cy.get(cesc("#\\/x13")).should("have.text", "z"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/x1"].stateValues.value).eq("1"); - expect(stateVariables["/x2"].stateValues.value).eq("15"); - expect(stateVariables["/x3"].stateValues.value).eq(222); - expect(stateVariables["/x4"].stateValues.value).eq(3); - expect(stateVariables["/x5"].stateValues.value).eq(5); - expect(stateVariables["/x6"].stateValues.value).eq(765); - expect(stateVariables["/x7"].stateValues.value).eq(8); - expect(stateVariables["/x8"].stateValues.value).eq(99); - expect(stateVariables["/x9"].stateValues.value).eq("b"); - expect(stateVariables["/x10"].stateValues.value).eq("orange"); - expect(stateVariables["/x11"].stateValues.value).eq("u"); - expect(stateVariables["/x12"].stateValues.value).eq("x"); - expect(stateVariables["/x13"].stateValues.value).eq("z"); - }); - }); - - it("sort sugar type math", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- z b a x y c -

-

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let sorted = ["aaa", "bbb", "ccc", "xxx", "yyy", "zzz"]; - - cy.get(cesc("#\\/pList")).should("have.text", sorted.join(", ")); - cy.get(cesc("#\\/pNoList")).should("have.text", sorted.join("")); - }); - - it("sort sugar type number", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- 101 542 817 527 51 234 801 -

-

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let sorted = [51, 101, 234, 527, 542, 801, 817]; - - cy.get(cesc("#\\/pList")).should("have.text", sorted.join(", ")); - cy.get(cesc("#\\/pNoList")).should("have.text", sorted.join("")); - }); - - it("sort sugar type text", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

- orange - apple - banana - almost - above -

-

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); - - let sorted = ["above", "almost", "apple", "banana", "orange"]; - - cy.get(cesc("#\\/pList")).should("have.text", sorted.join(", ")); - cy.get(cesc("#\\/pNoList")).should("have.text", sorted.join("")); - }); -}); 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"); - }); - }); -}); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/textinput.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/textinput.cy.js index 526d4c882..4c670bf94 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/textinput.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/textinput.cy.js @@ -10,1409 +10,6 @@ describe("TextInput Tag Tests", function () { cy.visit("/"); }); - it("textinput references", () => { - // A fairly involved test - // to check for bugs that have shown up only after multiple manipulations - - // Initial doenet code - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - $ti1.value{assignNames="v1"} - $ti1.immediateValue{assignNames="iv1"} - $ti1a.value{assignNames="v1a"} - $ti1a.immediateValue{assignNames="iv1a"} - - $ti2.value{assignNames="v2"} - $ti2.immediateValue{assignNames="iv2"} - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/ti1_input")).should("have.value", "hello"); - cy.get(cesc("#\\/ti1a_input")).should("have.value", "hello"); - cy.get(cesc("#\\/ti2_input")).should("have.value", ""); - - cy.get(cesc("#\\/v1")).should("have.text", "hello"); - cy.get(cesc("#\\/iv1")).should("have.text", "hello"); - cy.get(cesc("#\\/v1a")).should("have.text", "hello"); - cy.get(cesc("#\\/iv1a")).should("have.text", "hello"); - cy.get(cesc("#\\/v2")).should("have.text", ""); - cy.get(cesc("#\\/iv2")).should("have.text", ""); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ti1"].stateValues.immediateValue).eq( - "hello", - ); - expect(stateVariables["/ti1a"].stateValues.immediateValue).eq( - "hello", - ); - expect(stateVariables["/ti2"].stateValues.immediateValue).eq(""); - expect(stateVariables["/ti1"].stateValues.value).eq("hello"); - expect(stateVariables["/ti1a"].stateValues.value).eq("hello"); - expect(stateVariables["/ti2"].stateValues.value).eq(""); - }); - - // type 2 in first input - - cy.log("Typing 2 in first textinput"); - cy.get(cesc("#\\/ti1_input")).type(`2`); - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/ti1_input")).should("have.value", "hello2"); - cy.get(cesc("#\\/ti1a_input")).should("have.value", "hello2"); - cy.get(cesc("#\\/ti2_input")).should("have.value", ""); - - cy.get(cesc("#\\/v1")).should("have.text", "hello"); - cy.get(cesc("#\\/iv1")).should("have.text", "hello2"); - cy.get(cesc("#\\/v1a")).should("have.text", "hello"); - cy.get(cesc("#\\/iv1a")).should("have.text", "hello2"); - cy.get(cesc("#\\/v2")).should("have.text", ""); - cy.get(cesc("#\\/iv2")).should("have.text", ""); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ti1"].stateValues.immediateValue).eq( - "hello2", - ); - expect(stateVariables["/ti1a"].stateValues.immediateValue).eq( - "hello2", - ); - expect(stateVariables["/ti2"].stateValues.immediateValue).eq(""); - expect(stateVariables["/ti1"].stateValues.value).eq("hello"); - expect(stateVariables["/ti1a"].stateValues.value).eq("hello"); - expect(stateVariables["/ti2"].stateValues.value).eq(""); - }); - - // press enter in first input - - cy.log("Pressing Enter in first textinput"); - cy.get(cesc("#\\/ti1_input")).type(`{enter}`); - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/ti1_input")).should("have.value", "hello2"); - cy.get(cesc("#\\/ti1a_input")).should("have.value", "hello2"); - cy.get(cesc("#\\/ti2_input")).should("have.value", ""); - - cy.get(cesc("#\\/v1")).should("have.text", "hello2"); - cy.get(cesc("#\\/iv1")).should("have.text", "hello2"); - cy.get(cesc("#\\/v1a")).should("have.text", "hello2"); - cy.get(cesc("#\\/iv1a")).should("have.text", "hello2"); - cy.get(cesc("#\\/v2")).should("have.text", ""); - cy.get(cesc("#\\/iv2")).should("have.text", ""); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ti1"].stateValues.immediateValue).eq( - "hello2", - ); - expect(stateVariables["/ti1a"].stateValues.immediateValue).eq( - "hello2", - ); - expect(stateVariables["/ti2"].stateValues.immediateValue).eq(""); - expect(stateVariables["/ti1"].stateValues.value).eq("hello2"); - expect(stateVariables["/ti1a"].stateValues.value).eq("hello2"); - expect(stateVariables["/ti2"].stateValues.value).eq(""); - }); - - // erase "2" and type " you" in second input - - cy.log(`Erasing "2" and typing " you" in second textinput`); - cy.get(cesc("#\\/ti1a_input")).type(`{backspace} you`); - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/ti1_input")).should("have.value", "hello you"); - cy.get(cesc("#\\/ti1a_input")).should("have.value", "hello you"); - cy.get(cesc("#\\/ti2_input")).should("have.value", ""); - - cy.get(cesc("#\\/v1")).should("have.text", "hello2"); - cy.get(cesc("#\\/iv1")).should("have.text", "hello you"); - cy.get(cesc("#\\/v1a")).should("have.text", "hello2"); - cy.get(cesc("#\\/iv1a")).should("have.text", "hello you"); - cy.get(cesc("#\\/v2")).should("have.text", ""); - cy.get(cesc("#\\/iv2")).should("have.text", ""); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ti1"].stateValues.immediateValue).eq( - "hello you", - ); - expect(stateVariables["/ti1a"].stateValues.immediateValue).eq( - "hello you", - ); - expect(stateVariables["/ti2"].stateValues.immediateValue).eq(""); - expect(stateVariables["/ti1"].stateValues.value).eq("hello2"); - expect(stateVariables["/ti1a"].stateValues.value).eq("hello2"); - expect(stateVariables["/ti2"].stateValues.value).eq(""); - }); - - // change focus to textinput 1 - cy.log("Changing focus to first textinput"); - cy.get(cesc("#\\/ti1_input")).focus(); - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/ti1_input")).should("have.value", "hello you"); - cy.get(cesc("#\\/ti1a_input")).should("have.value", "hello you"); - cy.get(cesc("#\\/ti2_input")).should("have.value", ""); - - cy.get(cesc("#\\/v1")).should("have.text", "hello you"); - cy.get(cesc("#\\/iv1")).should("have.text", "hello you"); - cy.get(cesc("#\\/v1a")).should("have.text", "hello you"); - cy.get(cesc("#\\/iv1a")).should("have.text", "hello you"); - cy.get(cesc("#\\/v2")).should("have.text", ""); - cy.get(cesc("#\\/iv2")).should("have.text", ""); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ti1"].stateValues.immediateValue).eq( - "hello you", - ); - expect(stateVariables["/ti1a"].stateValues.immediateValue).eq( - "hello you", - ); - expect(stateVariables["/ti2"].stateValues.immediateValue).eq(""); - expect(stateVariables["/ti1"].stateValues.value).eq("hello you"); - expect(stateVariables["/ti1a"].stateValues.value).eq("hello you"); - expect(stateVariables["/ti2"].stateValues.value).eq(""); - }); - - // bye in third input - - cy.log(`Typing "bye" in third textinput`); - cy.get(cesc("#\\/ti2_input")).type(`bye`); - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/ti1_input")).should("have.value", "hello you"); - cy.get(cesc("#\\/ti1a_input")).should("have.value", "hello you"); - cy.get(cesc("#\\/ti2_input")).should("have.value", "bye"); - - cy.get(cesc("#\\/v1")).should("have.text", "hello you"); - cy.get(cesc("#\\/iv1")).should("have.text", "hello you"); - cy.get(cesc("#\\/v1a")).should("have.text", "hello you"); - cy.get(cesc("#\\/iv1a")).should("have.text", "hello you"); - cy.get(cesc("#\\/v2")).should("have.text", ""); - cy.get(cesc("#\\/iv2")).should("have.text", "bye"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ti1"].stateValues.immediateValue).eq( - "hello you", - ); - expect(stateVariables["/ti1a"].stateValues.immediateValue).eq( - "hello you", - ); - expect(stateVariables["/ti2"].stateValues.immediateValue).eq("bye"); - expect(stateVariables["/ti1"].stateValues.value).eq("hello you"); - expect(stateVariables["/ti1a"].stateValues.value).eq("hello you"); - expect(stateVariables["/ti2"].stateValues.value).eq(""); - }); - - // press enter in textinput 3 - - cy.log("Pressing enter in third textinput"); - cy.get(cesc("#\\/ti2_input")).type(`{enter}`); - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/ti1_input")).should("have.value", "hello you"); - cy.get(cesc("#\\/ti1a_input")).should("have.value", "hello you"); - cy.get(cesc("#\\/ti2_input")).should("have.value", "bye"); - - cy.get(cesc("#\\/v1")).should("have.text", "hello you"); - cy.get(cesc("#\\/iv1")).should("have.text", "hello you"); - cy.get(cesc("#\\/v1a")).should("have.text", "hello you"); - cy.get(cesc("#\\/iv1a")).should("have.text", "hello you"); - cy.get(cesc("#\\/v2")).should("have.text", "bye"); - cy.get(cesc("#\\/iv2")).should("have.text", "bye"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ti1"].stateValues.immediateValue).eq( - "hello you", - ); - expect(stateVariables["/ti1a"].stateValues.immediateValue).eq( - "hello you", - ); - expect(stateVariables["/ti2"].stateValues.immediateValue).eq("bye"); - expect(stateVariables["/ti1"].stateValues.value).eq("hello you"); - expect(stateVariables["/ti1a"].stateValues.value).eq("hello you"); - expect(stateVariables["/ti2"].stateValues.value).eq("bye"); - }); - - // type abc enter in textinput 2 - - cy.log("Typing abc in second textinput"); - cy.get(cesc("#\\/ti1a_input")).clear().type(`abc`); - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/ti1_input")).should("have.value", "abc"); - cy.get(cesc("#\\/ti1a_input")).should("have.value", "abc"); - cy.get(cesc("#\\/ti2_input")).should("have.value", "bye"); - - cy.get(cesc("#\\/v1")).should("have.text", "hello you"); - cy.get(cesc("#\\/iv1")).should("have.text", "abc"); - cy.get(cesc("#\\/v1a")).should("have.text", "hello you"); - cy.get(cesc("#\\/iv1a")).should("have.text", "abc"); - cy.get(cesc("#\\/v2")).should("have.text", "bye"); - cy.get(cesc("#\\/iv2")).should("have.text", "bye"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ti1"].stateValues.immediateValue).eq("abc"); - expect(stateVariables["/ti1a"].stateValues.immediateValue).eq( - "abc", - ); - expect(stateVariables["/ti2"].stateValues.immediateValue).eq("bye"); - expect(stateVariables["/ti1"].stateValues.value).eq("hello you"); - expect(stateVariables["/ti1a"].stateValues.value).eq("hello you"); - expect(stateVariables["/ti2"].stateValues.value).eq("bye"); - }); - - // press enter in textinput 2 - - cy.log("Pressing enter in second textinput"); - cy.get(cesc("#\\/ti1a_input")).type(`{enter}`); - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/ti1_input")).should("have.value", "abc"); - cy.get(cesc("#\\/ti1a_input")).should("have.value", "abc"); - cy.get(cesc("#\\/ti2_input")).should("have.value", "bye"); - - cy.get(cesc("#\\/v1")).should("have.text", "abc"); - cy.get(cesc("#\\/iv1")).should("have.text", "abc"); - cy.get(cesc("#\\/v1a")).should("have.text", "abc"); - cy.get(cesc("#\\/iv1a")).should("have.text", "abc"); - cy.get(cesc("#\\/v2")).should("have.text", "bye"); - cy.get(cesc("#\\/iv2")).should("have.text", "bye"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ti1"].stateValues.immediateValue).eq("abc"); - expect(stateVariables["/ti1a"].stateValues.immediateValue).eq( - "abc", - ); - expect(stateVariables["/ti2"].stateValues.immediateValue).eq("bye"); - expect(stateVariables["/ti1"].stateValues.value).eq("abc"); - expect(stateVariables["/ti1a"].stateValues.value).eq("abc"); - expect(stateVariables["/ti2"].stateValues.value).eq("bye"); - }); - - // type abc in textinput 1 - - cy.log("Typing abc in first textinput"); - cy.get(cesc("#\\/ti1_input")).clear().type(`abc`); - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/ti1_input")).should("have.value", "abc"); - cy.get(cesc("#\\/ti1a_input")).should("have.value", "abc"); - cy.get(cesc("#\\/ti2_input")).should("have.value", "bye"); - - cy.get(cesc("#\\/v1")).should("have.text", "abc"); - cy.get(cesc("#\\/iv1")).should("have.text", "abc"); - cy.get(cesc("#\\/v1a")).should("have.text", "abc"); - cy.get(cesc("#\\/iv1a")).should("have.text", "abc"); - cy.get(cesc("#\\/v2")).should("have.text", "bye"); - cy.get(cesc("#\\/iv2")).should("have.text", "bye"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ti1"].stateValues.immediateValue).eq("abc"); - expect(stateVariables["/ti1a"].stateValues.immediateValue).eq( - "abc", - ); - expect(stateVariables["/ti2"].stateValues.immediateValue).eq("bye"); - expect(stateVariables["/ti1"].stateValues.value).eq("abc"); - expect(stateVariables["/ti1a"].stateValues.value).eq("abc"); - expect(stateVariables["/ti2"].stateValues.value).eq("bye"); - }); - - // type saludos in textinput 3 - - cy.log("Typing saludos in third textinput"); - cy.get(cesc("#\\/ti2_input")).clear().type(`saludos`); - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/ti1_input")).should("have.value", "abc"); - cy.get(cesc("#\\/ti1a_input")).should("have.value", "abc"); - cy.get(cesc("#\\/ti2_input")).should("have.value", "saludos"); - - cy.get(cesc("#\\/v1")).should("have.text", "abc"); - cy.get(cesc("#\\/iv1")).should("have.text", "abc"); - cy.get(cesc("#\\/v1a")).should("have.text", "abc"); - cy.get(cesc("#\\/iv1a")).should("have.text", "abc"); - cy.get(cesc("#\\/v2")).should("have.text", "bye"); - cy.get(cesc("#\\/iv2")).should("have.text", "saludos"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ti1"].stateValues.immediateValue).eq("abc"); - expect(stateVariables["/ti1a"].stateValues.immediateValue).eq( - "abc", - ); - expect(stateVariables["/ti2"].stateValues.immediateValue).eq( - "saludos", - ); - expect(stateVariables["/ti1"].stateValues.value).eq("abc"); - expect(stateVariables["/ti1a"].stateValues.value).eq("abc"); - expect(stateVariables["/ti2"].stateValues.value).eq("bye"); - }); - - // type d in textinput 1 - - cy.log("Typing d in first textinput"); - cy.get(cesc("#\\/ti1_input")).type(`d`); - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/ti1_input")).should("have.value", "abcd"); - cy.get(cesc("#\\/ti1a_input")).should("have.value", "abcd"); - cy.get(cesc("#\\/ti2_input")).should("have.value", "saludos"); - - cy.get(cesc("#\\/v1")).should("have.text", "abc"); - cy.get(cesc("#\\/iv1")).should("have.text", "abcd"); - cy.get(cesc("#\\/v1a")).should("have.text", "abc"); - cy.get(cesc("#\\/iv1a")).should("have.text", "abcd"); - cy.get(cesc("#\\/v2")).should("have.text", "saludos"); - cy.get(cesc("#\\/iv2")).should("have.text", "saludos"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ti1"].stateValues.immediateValue).eq( - "abcd", - ); - expect(stateVariables["/ti1a"].stateValues.immediateValue).eq( - "abcd", - ); - expect(stateVariables["/ti2"].stateValues.immediateValue).eq( - "saludos", - ); - expect(stateVariables["/ti1"].stateValues.value).eq("abc"); - expect(stateVariables["/ti1a"].stateValues.value).eq("abc"); - expect(stateVariables["/ti2"].stateValues.value).eq("saludos"); - }); - - cy.log("Typing enter in first textinput"); - cy.get(cesc("#\\/ti1_input")).type(`{enter}`); - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/ti1_input")).should("have.value", "abcd"); - cy.get(cesc("#\\/ti1a_input")).should("have.value", "abcd"); - cy.get(cesc("#\\/ti2_input")).should("have.value", "saludos"); - - cy.get(cesc("#\\/v1")).should("have.text", "abcd"); - cy.get(cesc("#\\/iv1")).should("have.text", "abcd"); - cy.get(cesc("#\\/v1a")).should("have.text", "abcd"); - cy.get(cesc("#\\/iv1a")).should("have.text", "abcd"); - cy.get(cesc("#\\/v2")).should("have.text", "saludos"); - cy.get(cesc("#\\/iv2")).should("have.text", "saludos"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ti1"].stateValues.immediateValue).eq( - "abcd", - ); - expect(stateVariables["/ti1a"].stateValues.immediateValue).eq( - "abcd", - ); - expect(stateVariables["/ti2"].stateValues.immediateValue).eq( - "saludos", - ); - expect(stateVariables["/ti1"].stateValues.value).eq("abcd"); - expect(stateVariables["/ti1a"].stateValues.value).eq("abcd"); - expect(stateVariables["/ti2"].stateValues.value).eq("saludos"); - }); - - cy.log("Clearing second textinput"); - cy.get(cesc("#\\/ti1a_input")).clear(); - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/ti1_input")).should("have.value", ""); - cy.get(cesc("#\\/ti1a_input")).should("have.value", ""); - cy.get(cesc("#\\/ti2_input")).should("have.value", "saludos"); - - cy.get(cesc("#\\/v1")).should("have.text", "abcd"); - cy.get(cesc("#\\/iv1")).should("have.text", ""); - cy.get(cesc("#\\/v1a")).should("have.text", "abcd"); - cy.get(cesc("#\\/iv1a")).should("have.text", ""); - cy.get(cesc("#\\/v2")).should("have.text", "saludos"); - cy.get(cesc("#\\/iv2")).should("have.text", "saludos"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ti1"].stateValues.immediateValue).eq(""); - expect(stateVariables["/ti1a"].stateValues.immediateValue).eq(""); - expect(stateVariables["/ti2"].stateValues.immediateValue).eq( - "saludos", - ); - expect(stateVariables["/ti1"].stateValues.value).eq("abcd"); - expect(stateVariables["/ti1a"].stateValues.value).eq("abcd"); - expect(stateVariables["/ti2"].stateValues.value).eq("saludos"); - }); - - cy.log("pressing escape to undo"); - cy.get(cesc("#\\/ti1a_input")).type(`{esc}`); - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/ti1_input")).should("have.value", "abcd"); - cy.get(cesc("#\\/ti1a_input")).should("have.value", "abcd"); - cy.get(cesc("#\\/ti2_input")).should("have.value", "saludos"); - - cy.get(cesc("#\\/v1")).should("have.text", "abcd"); - cy.get(cesc("#\\/iv1")).should("have.text", "abcd"); - cy.get(cesc("#\\/v1a")).should("have.text", "abcd"); - cy.get(cesc("#\\/iv1a")).should("have.text", "abcd"); - cy.get(cesc("#\\/v2")).should("have.text", "saludos"); - cy.get(cesc("#\\/iv2")).should("have.text", "saludos"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ti1"].stateValues.immediateValue).eq( - "abcd", - ); - expect(stateVariables["/ti1a"].stateValues.immediateValue).eq( - "abcd", - ); - expect(stateVariables["/ti2"].stateValues.immediateValue).eq( - "saludos", - ); - expect(stateVariables["/ti1"].stateValues.value).eq("abcd"); - expect(stateVariables["/ti1a"].stateValues.value).eq("abcd"); - expect(stateVariables["/ti2"].stateValues.value).eq("saludos"); - }); - - cy.log("Type e in second textinput"); - cy.get(cesc("#\\/ti1a_input")).type(`e`); - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/ti1_input")).should("have.value", "abcde"); - cy.get(cesc("#\\/ti1a_input")).should("have.value", "abcde"); - cy.get(cesc("#\\/ti2_input")).should("have.value", "saludos"); - - cy.get(cesc("#\\/v1")).should("have.text", "abcd"); - cy.get(cesc("#\\/iv1")).should("have.text", "abcde"); - cy.get(cesc("#\\/v1a")).should("have.text", "abcd"); - cy.get(cesc("#\\/iv1a")).should("have.text", "abcde"); - cy.get(cesc("#\\/v2")).should("have.text", "saludos"); - cy.get(cesc("#\\/iv2")).should("have.text", "saludos"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ti1"].stateValues.immediateValue).eq( - "abcde", - ); - expect(stateVariables["/ti1a"].stateValues.immediateValue).eq( - "abcde", - ); - expect(stateVariables["/ti2"].stateValues.immediateValue).eq( - "saludos", - ); - expect(stateVariables["/ti1"].stateValues.value).eq("abcd"); - expect(stateVariables["/ti1a"].stateValues.value).eq("abcd"); - expect(stateVariables["/ti2"].stateValues.value).eq("saludos"); - }); - - cy.log("Escape in first input doesn't undo"); - cy.get(cesc("#\\/ti1_input")).type(`{Esc}`); - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/ti1_input")).should("have.value", "abcde"); - cy.get(cesc("#\\/ti1a_input")).should("have.value", "abcde"); - cy.get(cesc("#\\/ti2_input")).should("have.value", "saludos"); - - cy.get(cesc("#\\/v1")).should("have.text", "abcde"); - cy.get(cesc("#\\/iv1")).should("have.text", "abcde"); - cy.get(cesc("#\\/v1a")).should("have.text", "abcde"); - cy.get(cesc("#\\/iv1a")).should("have.text", "abcde"); - cy.get(cesc("#\\/v2")).should("have.text", "saludos"); - cy.get(cesc("#\\/iv2")).should("have.text", "saludos"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ti1"].stateValues.immediateValue).eq( - "abcde", - ); - expect(stateVariables["/ti1a"].stateValues.immediateValue).eq( - "abcde", - ); - expect(stateVariables["/ti2"].stateValues.immediateValue).eq( - "saludos", - ); - expect(stateVariables["/ti1"].stateValues.value).eq("abcde"); - expect(stateVariables["/ti1a"].stateValues.value).eq("abcde"); - expect(stateVariables["/ti2"].stateValues.value).eq("saludos"); - }); - - cy.log("Delete characters and replace in first input"); - cy.get(cesc("#\\/ti1_input")).type(`{backspace}{backspace}f`); - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/ti1_input")).should("have.value", "abcf"); - cy.get(cesc("#\\/ti1a_input")).should("have.value", "abcf"); - cy.get(cesc("#\\/ti2_input")).should("have.value", "saludos"); - - cy.get(cesc("#\\/v1")).should("have.text", "abcde"); - cy.get(cesc("#\\/iv1")).should("have.text", "abcf"); - cy.get(cesc("#\\/v1a")).should("have.text", "abcde"); - cy.get(cesc("#\\/iv1a")).should("have.text", "abcf"); - cy.get(cesc("#\\/v2")).should("have.text", "saludos"); - cy.get(cesc("#\\/iv2")).should("have.text", "saludos"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ti1"].stateValues.immediateValue).eq( - "abcf", - ); - expect(stateVariables["/ti1a"].stateValues.immediateValue).eq( - "abcf", - ); - expect(stateVariables["/ti2"].stateValues.immediateValue).eq( - "saludos", - ); - expect(stateVariables["/ti1"].stateValues.value).eq("abcde"); - expect(stateVariables["/ti1a"].stateValues.value).eq("abcde"); - expect(stateVariables["/ti2"].stateValues.value).eq("saludos"); - }); - - cy.log("Undo with escape"); - cy.get(cesc("#\\/ti1_input")).type(`{Esc}`); - - cy.log("Test values displayed in browser"); - cy.get(cesc("#\\/ti1_input")).should("have.value", "abcde"); - cy.get(cesc("#\\/ti1a_input")).should("have.value", "abcde"); - cy.get(cesc("#\\/ti2_input")).should("have.value", "saludos"); - - cy.get(cesc("#\\/v1")).should("have.text", "abcde"); - cy.get(cesc("#\\/iv1")).should("have.text", "abcde"); - cy.get(cesc("#\\/v1a")).should("have.text", "abcde"); - cy.get(cesc("#\\/iv1a")).should("have.text", "abcde"); - cy.get(cesc("#\\/v2")).should("have.text", "saludos"); - cy.get(cesc("#\\/iv2")).should("have.text", "saludos"); - - cy.log("Test internal values are set to the correct values"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ti1"].stateValues.immediateValue).eq( - "abcde", - ); - expect(stateVariables["/ti1a"].stateValues.immediateValue).eq( - "abcde", - ); - expect(stateVariables["/ti2"].stateValues.immediateValue).eq( - "saludos", - ); - expect(stateVariables["/ti1"].stateValues.value).eq("abcde"); - expect(stateVariables["/ti1a"].stateValues.value).eq("abcde"); - expect(stateVariables["/ti2"].stateValues.value).eq("saludos"); - }); - }); - - it("downstream from textinput", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

Original text: hello there

-

textinput based on text:

-

Copied textinput:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "hello there"); - - cy.get(cesc("#\\/_textinput1_input")).should( - "have.value", - "hello there", - ); - cy.get(cesc("#\\/textinput2_input")).should( - "have.value", - "hello there", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_textinput1"].stateValues.value).eq( - "hello there", - ); - expect( - stateVariables["/_textinput1"].stateValues.immediateValue, - ).eq("hello there"); - expect(stateVariables["/_text1"].stateValues.value).eq( - "hello there", - ); - expect(stateVariables["/textinput2"].stateValues.value).eq( - "hello there", - ); - expect(stateVariables["/textinput2"].stateValues.immediateValue).eq( - "hello there", - ); - }); - - cy.log("enter new values"); - cy.get(cesc("#\\/_textinput1_input")).clear().type(`bye now{enter}`); - - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "bye now"); - cy.get(cesc("#\\/textinput2_input")).should("have.value", "bye now"); - - cy.get(cesc("#\\/_text1")).should("have.text", "bye now"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_textinput1"].stateValues.value).eq( - "bye now", - ); - expect( - stateVariables["/_textinput1"].stateValues.immediateValue, - ).eq("bye now"); - expect(stateVariables["/_text1"].stateValues.value).eq("bye now"); - expect(stateVariables["/textinput2"].stateValues.value).eq( - "bye now", - ); - expect(stateVariables["/textinput2"].stateValues.immediateValue).eq( - "bye now", - ); - }); - - cy.log("prefill ignored"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

Original text: hello there

-

textinput based on text:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_textinput1_input")).should( - "have.value", - "hello there", - ); - - cy.get(cesc("#\\/_text1")).should("have.text", "hello there"); - - cy.log("values revert if not updatable"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

Original text: can't update me

-

textinput based on text:

-

immediate value: $_textinput1.immediateValue{assignNames="iv"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_textinput1_input")).should( - "have.value", - `can't update me`, - ); - - cy.get(cesc("#\\/_text1")).should("have.text", `can't update me`); - - cy.get(cesc("#\\/iv")).should("have.text", `can't update me`); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_textinput1"].stateValues.value).eq( - `can't update me`, - ); - expect( - stateVariables["/_textinput1"].stateValues.immediateValue, - ).eq(`can't update me`); - expect(stateVariables["/_text1"].stateValues.value).eq( - `can't update me`, - ); - }); - - cy.log("enter new values"); - cy.get(cesc("#\\/_textinput1_input")).clear().type(`disappear`); - - cy.get(cesc("#\\/_textinput1_input")).should("have.value", `disappear`); - - cy.get(cesc("#\\/_text1")).should("have.text", `can't update me`); - - cy.get(cesc("#\\/iv")).should("have.text", `disappear`); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_textinput1"].stateValues.value).eq( - `can't update me`, - ); - expect( - stateVariables["/_textinput1"].stateValues.immediateValue, - ).eq(`disappear`); - expect(stateVariables["/_text1"].stateValues.value).eq( - `can't update me`, - ); - }); - - cy.log("values revert when press enter"); - cy.get(cesc("#\\/_textinput1_input")).type(`{enter}`); - - cy.get(cesc("#\\/_textinput1_input")).should( - "have.value", - `can't update me`, - ); - - cy.get(cesc("#\\/_text1")).should("have.text", `can't update me`); - - cy.get(cesc("#\\/iv")).should("have.text", `can't update me`); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_textinput1"].stateValues.value).eq( - `can't update me`, - ); - expect( - stateVariables["/_textinput1"].stateValues.immediateValue, - ).eq(`can't update me`); - expect(stateVariables["/_text1"].stateValues.value).eq( - `can't update me`, - ); - }); - }); - - it("downstream from textinput via child", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

Original text: hello there

-

textinput based on text: $_text1

-

Copied textinput:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "hello there"); - - cy.get(cesc("#\\/_textinput1_input")).should( - "have.value", - "hello there", - ); - cy.get(cesc("#\\/textinput2_input")).should( - "have.value", - "hello there", - ); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_textinput1"].stateValues.value).eq( - "hello there", - ); - expect( - stateVariables["/_textinput1"].stateValues.immediateValue, - ).eq("hello there"); - expect(stateVariables["/_text1"].stateValues.value).eq( - "hello there", - ); - expect(stateVariables["/textinput2"].stateValues.value).eq( - "hello there", - ); - expect(stateVariables["/textinput2"].stateValues.immediateValue).eq( - "hello there", - ); - }); - - cy.log("enter new values"); - cy.get(cesc("#\\/_textinput1_input")).clear().type(`bye now{enter}`); - - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "bye now"); - cy.get(cesc("#\\/textinput2_input")).should("have.value", "bye now"); - - cy.get(cesc("#\\/_text1")).should("have.text", "bye now"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_textinput1"].stateValues.value).eq( - "bye now", - ); - expect( - stateVariables["/_textinput1"].stateValues.immediateValue, - ).eq("bye now"); - expect(stateVariables["/_text1"].stateValues.value).eq("bye now"); - expect(stateVariables["/textinput2"].stateValues.value).eq( - "bye now", - ); - expect(stateVariables["/textinput2"].stateValues.immediateValue).eq( - "bye now", - ); - }); - - cy.log("prefill ignored"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

Original text: hello there

-

textinput based on text: $_text1

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_textinput1_input")).should( - "have.value", - "hello there", - ); - - cy.get(cesc("#\\/_text1")).should("have.text", "hello there"); - - cy.log("prefill ignored, use string child"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

textinput based on text: Good morning

-

value:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_textinput1_input")).should( - "have.value", - "Good morning", - ); - - cy.get(cesc("#\\/_text1")).should("have.text", "Good morning"); - - cy.log("enter new values"); - cy.get(cesc("#\\/_textinput1_input")).clear().type(`Good night{enter}`); - - cy.get(cesc("#\\/_text1")).should("have.text", "Good night"); - - cy.log("bindvalue ignored, use string child"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

Ignore me: ignore

-

textinput based on text: Override with this

-

value:

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_textinput1_input")).should( - "have.value", - "Override with this", - ); - - cy.get(cesc("#\\/_text1")).should("have.text", "ignore"); - cy.get(cesc("#\\/_text2")).should("have.text", "Override with this"); - - cy.log("enter new values"); - cy.get(cesc("#\\/_textinput1_input")).clear().type(`Changed{enter}`); - - cy.get(cesc("#\\/_text1")).should("have.text", "ignore"); - cy.get(cesc("#\\/_text2")).should("have.text", "Changed"); - - cy.log("values revert if not updatable"); - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

Original text: update

-

textinput based on text: can't $_text1 me

-

immediate value: $_textinput1.immediateValue{assignNames="iv"}

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_textinput1_input")).should( - "have.value", - `can't update me`, - ); - - cy.get(cesc("#\\/_text1")).should("have.text", `update`); - - cy.get(cesc("#\\/iv")).should("have.text", `can't update me`); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_textinput1"].stateValues.value).eq( - `can't update me`, - ); - expect( - stateVariables["/_textinput1"].stateValues.immediateValue, - ).eq(`can't update me`); - expect(stateVariables["/_text1"].stateValues.value).eq(`update`); - }); - - cy.log("enter new values"); - cy.get(cesc("#\\/_textinput1_input")).clear().type(`disappear`); - - cy.get(cesc("#\\/_textinput1_input")).should("have.value", `disappear`); - - cy.get(cesc("#\\/_text1")).should("have.text", `update`); - - cy.get(cesc("#\\/iv")).should("have.text", `disappear`); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_textinput1"].stateValues.value).eq( - `can't update me`, - ); - expect( - stateVariables["/_textinput1"].stateValues.immediateValue, - ).eq(`disappear`); - expect(stateVariables["/_text1"].stateValues.value).eq(`update`); - }); - - cy.log("values revert when press enter"); - cy.get(cesc("#\\/_textinput1_input")).type(`{enter}`); - - cy.get(cesc("#\\/_textinput1_input")).should( - "have.value", - `can't update me`, - ); - - cy.get(cesc("#\\/_text1")).should("have.text", `update`); - - cy.get(cesc("#\\/iv")).should("have.text", `can't update me`); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/_textinput1"].stateValues.value).eq( - `can't update me`, - ); - expect( - stateVariables["/_textinput1"].stateValues.immediateValue, - ).eq(`can't update me`); - expect(stateVariables["/_text1"].stateValues.value).eq(`update`); - }); - }); - - it("textinput based on value of textinput", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

Original textinput:

-

textinput based on textinput:

-

Immediate value of original: $_textinput1.immediateValue

-

Value of original: $_textinput1.value

-

Immediate value of second: $_textinput2.immediateValue

-

Value of second: $_textinput2.value

- `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_textinput1_input")).should( - "have.value", - "hello there", - ); - cy.get(cesc("#\\/_textinput2_input")).should( - "have.value", - "hello there", - ); - - cy.get(cesc("#\\/originalimmediate")).should( - "have.text", - "hello there", - ); - cy.get(cesc("#\\/originalvalue")).should("have.text", "hello there"); - cy.get(cesc("#\\/secondimmediate")).should("have.text", "hello there"); - cy.get(cesc("#\\/secondvalue")).should("have.text", "hello there"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_textinput1"].stateValues.immediateValue, - ).eq("hello there"); - expect(stateVariables["/_textinput1"].stateValues.value).eq( - "hello there", - ); - expect( - stateVariables["/_textinput2"].stateValues.immediateValue, - ).eq("hello there"); - expect(stateVariables["/_textinput2"].stateValues.value).eq( - "hello there", - ); - }); - - cy.log("type new values in first textinput"); - cy.get(cesc("#\\/_textinput1_input")).clear().type(`bye now`); - - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "bye now"); - cy.get(cesc("#\\/_textinput2_input")).should( - "have.value", - "hello there", - ); - - cy.get(cesc("#\\/originalimmediate")).should("have.text", "bye now"); - cy.get(cesc("#\\/originalvalue")).should("have.text", "hello there"); - cy.get(cesc("#\\/secondimmediate")).should("have.text", "hello there"); - cy.get(cesc("#\\/secondvalue")).should("have.text", "hello there"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_textinput1"].stateValues.immediateValue, - ).eq("bye now"); - expect(stateVariables["/_textinput1"].stateValues.value).eq( - "hello there", - ); - expect( - stateVariables["/_textinput2"].stateValues.immediateValue, - ).eq("hello there"); - expect(stateVariables["/_textinput2"].stateValues.value).eq( - "hello there", - ); - }); - - cy.log("press enter"); - cy.get(cesc("#\\/_textinput1_input")).type(`{enter}`); - - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "bye now"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "bye now"); - - cy.get(cesc("#\\/originalimmediate")).should("have.text", "bye now"); - cy.get(cesc("#\\/originalvalue")).should("have.text", "bye now"); - cy.get(cesc("#\\/secondimmediate")).should("have.text", "bye now"); - cy.get(cesc("#\\/secondvalue")).should("have.text", "bye now"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_textinput1"].stateValues.immediateValue, - ).eq("bye now"); - expect(stateVariables["/_textinput1"].stateValues.value).eq( - "bye now", - ); - expect( - stateVariables["/_textinput2"].stateValues.immediateValue, - ).eq("bye now"); - expect(stateVariables["/_textinput2"].stateValues.value).eq( - "bye now", - ); - }); - - cy.log("type values input second textinput"); - cy.get(cesc("#\\/_textinput2_input")).clear().type(`Hello again`); - - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "bye now"); - cy.get(cesc("#\\/_textinput2_input")).should( - "have.value", - "Hello again", - ); - - cy.get(cesc("#\\/originalimmediate")).should("have.text", "bye now"); - cy.get(cesc("#\\/originalvalue")).should("have.text", "bye now"); - cy.get(cesc("#\\/secondimmediate")).should("have.text", "Hello again"); - cy.get(cesc("#\\/secondvalue")).should("have.text", "bye now"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_textinput1"].stateValues.immediateValue, - ).eq("bye now"); - expect(stateVariables["/_textinput1"].stateValues.value).eq( - "bye now", - ); - expect( - stateVariables["/_textinput2"].stateValues.immediateValue, - ).eq("Hello again"); - expect(stateVariables["/_textinput2"].stateValues.value).eq( - "bye now", - ); - }); - - cy.log("leave second textinput"); - cy.get(cesc("#\\/_textinput2_input")).blur(); - - cy.get(cesc("#\\/_textinput1_input")).should( - "have.value", - "Hello again", - ); - cy.get(cesc("#\\/_textinput2_input")).should( - "have.value", - "Hello again", - ); - - cy.get(cesc("#\\/originalimmediate")).should( - "have.text", - "Hello again", - ); - cy.get(cesc("#\\/originalvalue")).should("have.text", "Hello again"); - cy.get(cesc("#\\/secondimmediate")).should("have.text", "Hello again"); - cy.get(cesc("#\\/secondvalue")).should("have.text", "Hello again"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_textinput1"].stateValues.immediateValue, - ).eq("Hello again"); - expect(stateVariables["/_textinput1"].stateValues.value).eq( - "Hello again", - ); - expect( - stateVariables["/_textinput2"].stateValues.immediateValue, - ).eq("Hello again"); - expect(stateVariables["/_textinput2"].stateValues.value).eq( - "Hello again", - ); - }); - }); - - it("textinput based on immediateValue of textinput", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

Original textinput:

-

textinput based on textinput:

-

Immediate value of original: $_textinput1.immediateValue

-

Value of original: $_textinput1.value

-

Immediate value of second: $_textinput2.immediateValue

-

Value of second: $_textinput2.value

- - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_textinput1_input")).should( - "have.value", - "hello there", - ); - cy.get(cesc("#\\/_textinput2_input")).should( - "have.value", - "hello there", - ); - cy.get(cesc("#\\/originalimmediate")).should( - "have.text", - "hello there", - ); - cy.get(cesc("#\\/originalvalue")).should("have.text", "hello there"); - cy.get(cesc("#\\/secondimmediate")).should("have.text", "hello there"); - cy.get(cesc("#\\/secondvalue")).should("have.text", "hello there"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_textinput1"].stateValues.immediateValue, - ).eq("hello there"); - expect(stateVariables["/_textinput1"].stateValues.value).eq( - "hello there", - ); - expect( - stateVariables["/_textinput2"].stateValues.immediateValue, - ).eq("hello there"); - expect(stateVariables["/_textinput2"].stateValues.value).eq( - "hello there", - ); - }); - - cy.log("type new values in first textinput"); - cy.get(cesc("#\\/_textinput1_input")).clear().type(`bye now`); - - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "bye now"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "bye now"); - cy.get(cesc("#\\/originalimmediate")).should("have.text", "bye now"); - cy.get(cesc("#\\/originalvalue")).should("have.text", "hello there"); - cy.get(cesc("#\\/secondimmediate")).should("have.text", "bye now"); - cy.get(cesc("#\\/secondvalue")).should("have.text", "bye now"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_textinput1"].stateValues.immediateValue, - ).eq("bye now"); - expect(stateVariables["/_textinput1"].stateValues.value).eq( - "hello there", - ); - expect( - stateVariables["/_textinput2"].stateValues.immediateValue, - ).eq("bye now"); - expect(stateVariables["/_textinput2"].stateValues.value).eq( - "bye now", - ); - }); - - cy.log("press enter"); - cy.get(cesc("#\\/_textinput1_input")).type(`{enter}`); - - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "bye now"); - cy.get(cesc("#\\/_textinput2_input")).should("have.value", "bye now"); - cy.get(cesc("#\\/originalimmediate")).should("have.text", "bye now"); - cy.get(cesc("#\\/originalvalue")).should("have.text", "bye now"); - cy.get(cesc("#\\/secondimmediate")).should("have.text", "bye now"); - cy.get(cesc("#\\/secondvalue")).should("have.text", "bye now"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_textinput1"].stateValues.immediateValue, - ).eq("bye now"); - expect(stateVariables["/_textinput1"].stateValues.value).eq( - "bye now", - ); - expect( - stateVariables["/_textinput2"].stateValues.immediateValue, - ).eq("bye now"); - expect(stateVariables["/_textinput2"].stateValues.value).eq( - "bye now", - ); - }); - - cy.log("type values in second textinput"); - cy.get(cesc("#\\/_textinput2_input")).clear().type(`Hello again`); - - cy.get(cesc("#\\/_textinput1_input")).should("have.value", "bye now"); - cy.get(cesc("#\\/_textinput2_input")).should( - "have.value", - "Hello again", - ); - cy.get(cesc("#\\/originalimmediate")).should("have.text", "bye now"); - cy.get(cesc("#\\/originalvalue")).should("have.text", "bye now"); - cy.get(cesc("#\\/secondimmediate")).should("have.text", "Hello again"); - cy.get(cesc("#\\/secondvalue")).should("have.text", "bye now"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_textinput1"].stateValues.immediateValue, - ).eq("bye now"); - expect(stateVariables["/_textinput1"].stateValues.value).eq( - "bye now", - ); - expect( - stateVariables["/_textinput2"].stateValues.immediateValue, - ).eq("Hello again"); - expect(stateVariables["/_textinput2"].stateValues.value).eq( - "bye now", - ); - }); - - cy.log("leave second textinput, changes all values"); - cy.get(cesc("#\\/_textinput2_input")).blur(); - - cy.get(cesc("#\\/_textinput1_input")).should( - "have.value", - "Hello again", - ); - cy.get(cesc("#\\/_textinput2_input")).should( - "have.value", - "Hello again", - ); - cy.get(cesc("#\\/originalimmediate")).should( - "have.text", - "Hello again", - ); - cy.get(cesc("#\\/originalvalue")).should("have.text", "Hello again"); - cy.get(cesc("#\\/secondimmediate")).should("have.text", "Hello again"); - cy.get(cesc("#\\/secondvalue")).should("have.text", "Hello again"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect( - stateVariables["/_textinput1"].stateValues.immediateValue, - ).eq("Hello again"); - expect(stateVariables["/_textinput1"].stateValues.value).eq( - "Hello again", - ); - expect( - stateVariables["/_textinput2"].stateValues.immediateValue, - ).eq("Hello again"); - expect(stateVariables["/_textinput2"].stateValues.value).eq( - "Hello again", - ); - }); - }); - - it("chain update off textinput", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - $ti.immediateValue{assignNames="iv"} - - hello - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/h")).should("have.text", "hello"); - - cy.get(cesc("#\\/ti_input")).type(" bye"); - cy.get(cesc("#\\/iv")).should("have.text", " bye"); - cy.get(cesc("#\\/h")).should("have.text", "hello"); - - cy.get(cesc("#\\/ti_input")).clear().type(" there"); - cy.get(cesc("#\\/iv")).should("have.text", " there"); - cy.get(cesc("#\\/h")).should("have.text", "hello"); - - cy.get(cesc("#\\/ti_input")).blur(); - cy.get(cesc("#\\/iv")).should("have.text", " there"); - cy.get(cesc("#\\/h")).should("have.text", "hello there"); - - cy.get(cesc("#\\/ti_input")).clear().type("?"); - cy.get(cesc("#\\/iv")).should("have.text", "?"); - cy.get(cesc("#\\/h")).should("have.text", "hello there"); - - cy.get(cesc("#\\/ti_input")).clear().type("!"); - cy.get(cesc("#\\/iv")).should("have.text", "!"); - cy.get(cesc("#\\/h")).should("have.text", "hello there"); - - cy.get(cesc("#\\/ti_input")).type("{enter}"); - cy.get(cesc("#\\/iv")).should("have.text", "!"); - cy.get(cesc("#\\/h")).should("have.text", "hello there!"); - }); - it("expanded textinput", () => { cy.window().then(async (win) => { win.postMessage( @@ -1511,882 +108,4 @@ describe("TextInput Tag Tests", function () { cy.get(cesc("#\\/pv")).should("have.text", "value: hello"); cy.get(cesc("#\\/piv")).should("have.text", "immediate value: hello"); }); - - it("text input in graph", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - -

Anchor 1 coordinates: $textinput1.anchor

-

Anchor 2 coordinates: $textinput2.anchor

-

Change anchor 1 coordinates:

-

Change anchor 2 coordinates:

-

Position from anchor 1: $textinput1.positionFromAnchor

-

Position from anchor 2: $textinput2.positionFromAnchor

-

Change position from anchor 1 - - upperRight - upperLeft - lowerRight - lowerLeft - left - right - top - bottom - center - -

-

Change position from anchor 2 - - upperRight - upperLeft - lowerRight - lowerLeft - left - right - top - bottom - center - -

-

Draggable 1: $draggable1

-

Draggable 2: $draggable2

-

Change draggable 1

-

Change draggable 2

-

Disabled 1: $disabled1

-

Disabled 2: $disabled2

-

Change disabled 1

-

Change disabled 2

-

Fixed 1: $fixed1

-

Fixed 2: $fixed2

-

Change fixed 1

-

Change fixed 2

-

FixLocation 1: $fixLocation1

-

FixLocation 2: $fixLocation2

-

Change fixLocation 1

-

Change fixLocation 2

-

- - `, - }, - "*", - ); - }); - - // TODO: how to click on the checkboxes and test if they are disabled? - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,3)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,0)"); - - cy.get(cesc("#\\/pPositionFromAnchor1")).should( - "have.text", - "Position from anchor 1: upperright", - ); - cy.get(cesc("#\\/pPositionFromAnchor2")).should( - "have.text", - "Position from anchor 2: center", - ); - cy.get(cesc("#\\/positionFromAnchor1")).should("have.value", "1"); - cy.get(cesc("#\\/positionFromAnchor2")).should("have.value", "9"); - cy.get(cesc("#\\/pDraggable1")).should( - "have.text", - "Draggable 1: true", - ); - cy.get(cesc("#\\/pDraggable2")).should( - "have.text", - "Draggable 2: true", - ); - - cy.log("move textinputs by dragging"); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveInput", - componentName: "/textinput1", - args: { x: -2, y: 3 }, - }); - win.callAction1({ - actionName: "moveInput", - componentName: "/textinput2", - args: { x: 4, y: -5 }, - }); - }); - - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow").should( - "contain.text", - "(4,−5)", - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−2,3)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(4,−5)"); - - cy.log("move textinputs by entering coordinates"); - - cy.get(cesc("#\\/anchorCoords1") + " textarea").type( - "{home}{shift+end}{backspace}(6,7){enter}", - { force: true }, - ); - cy.get(cesc("#\\/anchorCoords2") + " textarea").type( - "{home}{shift+end}{backspace}(8,9){enter}", - { force: true }, - ); - - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow").should( - "contain.text", - "(8,9)", - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(6,7)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(8,9)"); - - cy.log("change position from anchor"); - cy.get(cesc("#\\/positionFromAnchor1")).select("lowerLeft"); - cy.get(cesc("#\\/positionFromAnchor2")).select("lowerRight"); - - cy.get(cesc("#\\/pPositionFromAnchor1")).should( - "have.text", - "Position from anchor 1: lowerleft", - ); - cy.get(cesc("#\\/pPositionFromAnchor2")).should( - "have.text", - "Position from anchor 2: lowerright", - ); - - cy.log("make not draggable"); - - cy.get(cesc("#\\/draggable1")).click(); - cy.get(cesc("#\\/draggable2")).click(); - cy.get(cesc("#\\/pDraggable1")).should( - "have.text", - "Draggable 1: false", - ); - cy.get(cesc("#\\/pDraggable2")).should( - "have.text", - "Draggable 2: false", - ); - - cy.log("cannot move textinputs by dragging"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveInput", - componentName: "/textinput1", - args: { x: -10, y: -9 }, - }); - win.callAction1({ - actionName: "moveInput", - componentName: "/textinput2", - args: { x: -8, y: -7 }, - }); - }); - - // since nothing will change, wait for boolean input to change to know core has responded - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/b")).should("have.text", "true"); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(6,7)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(8,9)"); - - cy.log("make draggable again"); - - cy.get(cesc("#\\/draggable1")).click(); - cy.get(cesc("#\\/draggable2")).click(); - cy.get(cesc("#\\/pDraggable1")).should( - "have.text", - "Draggable 1: true", - ); - cy.get(cesc("#\\/pDraggable2")).should( - "have.text", - "Draggable 2: true", - ); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveInput", - componentName: "/textinput1", - args: { x: -10, y: -9 }, - }); - win.callAction1({ - actionName: "moveInput", - componentName: "/textinput2", - args: { x: -8, y: -7 }, - }); - }); - - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow").should( - "contain.text", - "(−8,−7)", - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−10,−9)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−8,−7)"); - - cy.log("fix location"); - - cy.get(cesc("#\\/fixLocation1")).click(); - cy.get(cesc("#\\/fixLocation2")).click(); - cy.get(cesc("#\\/pFixLocation1")).should( - "have.text", - "FixLocation 1: true", - ); - cy.get(cesc("#\\/pFixLocation2")).should( - "have.text", - "FixLocation 2: true", - ); - - cy.log("can change coordinates entering coordinates only for input 1"); - - cy.get(cesc("#\\/anchorCoords2") + " textarea").type( - "{home}{shift+end}{backspace}(3,4){enter}", - { force: true }, - ); - cy.get(cesc("#\\/anchorCoords1") + " textarea").type( - "{home}{shift+end}{backspace}(1,2){enter}", - { force: true }, - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow").should( - "contain.text", - "(1,2)", - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−8,−7)"); - - cy.log("cannot move textinputs by dragging"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveInput", - componentName: "/textinput1", - args: { x: 4, y: 6 }, - }); - win.callAction1({ - actionName: "moveInput", - componentName: "/textinput2", - args: { x: 7, y: 8 }, - }); - }); - - // since nothing will change, wait for boolean input to change to know core has responded - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/b")).should("have.text", "false"); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−8,−7)"); - - cy.log("can change position from anchor only for input 1"); - cy.get(cesc("#\\/positionFromAnchor2")).select("bottom"); - cy.get(cesc("#\\/positionFromAnchor1")).select("top"); - - cy.get(cesc("#\\/pPositionFromAnchor1")).should( - "have.text", - "Position from anchor 1: top", - ); - cy.get(cesc("#\\/pPositionFromAnchor2")).should( - "have.text", - "Position from anchor 2: lowerright", - ); - - cy.log("can change disabled attribute"); - cy.get(cesc("#\\/disabled1")).click(); - cy.get(cesc("#\\/disabled2")).click(); - cy.get(cesc("#\\/pDisabled1")).should("have.text", "Disabled 1: false"); - cy.get(cesc("#\\/pDisabled2")).should("have.text", "Disabled 2: true"); - - cy.log("make completely fixed"); - cy.get(cesc("#\\/fixed1")).click(); - cy.get(cesc("#\\/fixed2")).click(); - cy.get(cesc("#\\/pFixed1")).should("have.text", "Fixed 1: true"); - cy.get(cesc("#\\/pFixed2")).should("have.text", "Fixed 2: true"); - - cy.log("can change coordinates entering coordinates only for input 1"); - - cy.get(cesc("#\\/anchorCoords2") + " textarea").type( - "{home}{shift+end}{backspace}(7,8){enter}", - { force: true }, - ); - cy.get(cesc("#\\/anchorCoords1") + " textarea").type( - "{home}{shift+end}{backspace}(5,6){enter}", - { force: true }, - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow").should( - "contain.text", - "(5,6)", - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(5,6)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−8,−7)"); - - cy.log("can change position from anchor only for input 1"); - cy.get(cesc("#\\/positionFromAnchor2")).select("left"); - cy.get(cesc("#\\/positionFromAnchor1")).select("right"); - - cy.get(cesc("#\\/pPositionFromAnchor1")).should( - "have.text", - "Position from anchor 1: right", - ); - cy.get(cesc("#\\/pPositionFromAnchor2")).should( - "have.text", - "Position from anchor 2: lowerright", - ); - - cy.log("can change disabled attribute only for input 1"); - cy.get(cesc("#\\/disabled2")).click(); - cy.get(cesc("#\\/disabled1")).click(); - cy.get(cesc("#\\/pDisabled1")).should("have.text", "Disabled 1: true"); - cy.get(cesc("#\\/pDisabled2")).should("have.text", "Disabled 2: true"); - }); - - it("use textinput as basic math input", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - -

Math from text input: $ti

-

Number from text input: $ti

-

Math via latex from text input: $ti.value{isLatex}

-

Number via latex from text input: $ti.value{isLatex}

- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc2("#/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc2("#/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc2("#/n1")).should("have.text", "NaN"); - cy.get(cesc2("#/n2")).should("have.text", "NaN"); - - cy.get(cesc2("#/ti_input")).type("4/2{enter}"); - - cy.get(cesc2("#/m1") + " .mjx-mrow").should("contain.text", "42"); - cy.get(cesc2("#/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "42"); - cy.get(cesc2("#/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "42"); - cy.get(cesc2("#/n1")).should("have.text", "2"); - cy.get(cesc2("#/n2")).should("have.text", "2"); - - cy.get(cesc2("#/ti_input")).clear().type("xy{enter}"); - - cy.get(cesc2("#/m1") + " .mjx-mrow").should("contain.text", "xy"); - cy.get(cesc2("#/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "xy"); - cy.get(cesc2("#/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "xy"); - cy.get(cesc2("#/n1")).should("have.text", "NaN"); - cy.get(cesc2("#/n2")).should("have.text", "NaN"); - - cy.get(cesc2("#/ti_input")).clear().type("\\frac{{}a}{{}b}{enter}"); - - cy.get(cesc2("#/m1") + " .mjx-mrow").should("contain.text", "\uff3f"); - cy.get(cesc2("#/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc2("#/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "ab"); - cy.get(cesc2("#/n1")).should("have.text", "NaN"); - cy.get(cesc2("#/n2")).should("have.text", "NaN"); - - cy.get(cesc2("#/ti_input")).clear().type("\\frac{{}6}{{}2}{enter}"); - - cy.get(cesc2("#/m2") + " .mjx-mrow").should("contain.text", "62"); - cy.get(cesc2("#/m1") + " .mjx-mrow") - .eq(0) - .should("have.text", "\uff3f"); - cy.get(cesc2("#/m2") + " .mjx-mrow") - .eq(0) - .should("have.text", "62"); - cy.get(cesc2("#/n1")).should("have.text", "NaN"); - cy.get(cesc2("#/n2")).should("have.text", "3"); - }); - - it("valueChanged", () => { - let doenetML = ` -

-

-

-

$ti2.immediateValue

- - `; - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - }, - "*", - ); - }); - - cy.get(cesc2("#/ti1a")).should("have.text", ""); - cy.get(cesc2("#/ti2a")).should("have.text", "apple"); - cy.get(cesc2("#/ti3a")).should("have.text", ""); - cy.get(cesc2("#/ti4a")).should("have.text", "apple"); - - cy.get(cesc2("#/ti1iva")).should("have.text", ""); - cy.get(cesc2("#/ti2iva")).should("have.text", "apple"); - cy.get(cesc2("#/ti3iva")).should("have.text", ""); - cy.get(cesc2("#/ti4iva")).should("have.text", "apple"); - - cy.get(cesc2("#/ti1changed")).should("have.text", "false"); - cy.get(cesc2("#/ti2changed")).should("have.text", "false"); - cy.get(cesc2("#/ti3changed")).should("have.text", "false"); - cy.get(cesc2("#/ti4changed")).should("have.text", "false"); - - cy.get(cesc2("#/ti1ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/ti2ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/ti3ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/ti4ivchanged")).should("have.text", "false"); - - cy.log("type in first marks only first immediate value as changed"); - - cy.get(cesc2("#/ti1") + "_input").type("banana"); - - cy.get(cesc2("#/ti1iva")).should("have.text", "banana"); - - cy.get(cesc2("#/ti1a")).should("have.text", ""); - cy.get(cesc2("#/ti2a")).should("have.text", "apple"); - cy.get(cesc2("#/ti3a")).should("have.text", ""); - cy.get(cesc2("#/ti4a")).should("have.text", "apple"); - - cy.get(cesc2("#/ti1iva")).should("have.text", "banana"); - cy.get(cesc2("#/ti2iva")).should("have.text", "apple"); - cy.get(cesc2("#/ti3iva")).should("have.text", ""); - cy.get(cesc2("#/ti4iva")).should("have.text", "apple"); - - cy.get(cesc2("#/ti1changed")).should("have.text", "false"); - cy.get(cesc2("#/ti2changed")).should("have.text", "false"); - cy.get(cesc2("#/ti3changed")).should("have.text", "false"); - cy.get(cesc2("#/ti4changed")).should("have.text", "false"); - - cy.get(cesc2("#/ti1ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/ti2ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/ti3ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/ti4ivchanged")).should("have.text", "false"); - - cy.log("press enter in first marks only first value as changed"); - - cy.get(cesc2("#/ti1") + "_input").type("{enter}"); - - cy.get(cesc2("#/ti1a")).should("have.text", "banana"); - - cy.get(cesc2("#/ti1a")).should("have.text", "banana"); - cy.get(cesc2("#/ti2a")).should("have.text", "apple"); - cy.get(cesc2("#/ti3a")).should("have.text", "banana"); - cy.get(cesc2("#/ti4a")).should("have.text", "apple"); - - cy.get(cesc2("#/ti1iva")).should("have.text", "banana"); - cy.get(cesc2("#/ti2iva")).should("have.text", "apple"); - cy.get(cesc2("#/ti3iva")).should("have.text", "banana"); - cy.get(cesc2("#/ti4iva")).should("have.text", "apple"); - - cy.get(cesc2("#/ti1changed")).should("have.text", "true"); - cy.get(cesc2("#/ti2changed")).should("have.text", "false"); - cy.get(cesc2("#/ti3changed")).should("have.text", "false"); - cy.get(cesc2("#/ti4changed")).should("have.text", "false"); - - cy.get(cesc2("#/ti1ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/ti2ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/ti3ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/ti4ivchanged")).should("have.text", "false"); - - cy.log("type in second marks only second immediate value as changed"); - - cy.get(cesc2("#/ti2") + "_input") - .clear() - .type("cherry", { - force: true, - }); - - cy.get(cesc2("#/ti2iva")).should("have.text", "cherry"); - - cy.get(cesc2("#/ti1a")).should("have.text", "banana"); - cy.get(cesc2("#/ti2a")).should("have.text", "apple"); - cy.get(cesc2("#/ti3a")).should("have.text", "banana"); - cy.get(cesc2("#/ti4a")).should("have.text", "cherry"); - - cy.get(cesc2("#/ti1iva")).should("have.text", "banana"); - cy.get(cesc2("#/ti2iva")).should("have.text", "cherry"); - cy.get(cesc2("#/ti3iva")).should("have.text", "banana"); - cy.get(cesc2("#/ti4iva")).should("have.text", "cherry"); - - cy.get(cesc2("#/ti1changed")).should("have.text", "true"); - cy.get(cesc2("#/ti2changed")).should("have.text", "false"); - cy.get(cesc2("#/ti3changed")).should("have.text", "false"); - cy.get(cesc2("#/ti4changed")).should("have.text", "false"); - - cy.get(cesc2("#/ti1ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/ti2ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/ti3ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/ti4ivchanged")).should("have.text", "false"); - - cy.log("press enter in second marks only second value as changed"); - - cy.get(cesc2("#/ti2") + "_input").type("{enter}"); - - cy.get(cesc2("#/ti2a")).should("have.text", "cherry"); - - cy.get(cesc2("#/ti1a")).should("have.text", "banana"); - cy.get(cesc2("#/ti2a")).should("have.text", "cherry"); - cy.get(cesc2("#/ti3a")).should("have.text", "banana"); - cy.get(cesc2("#/ti4a")).should("have.text", "cherry"); - - cy.get(cesc2("#/ti1iva")).should("have.text", "banana"); - cy.get(cesc2("#/ti2iva")).should("have.text", "cherry"); - cy.get(cesc2("#/ti3iva")).should("have.text", "banana"); - cy.get(cesc2("#/ti4iva")).should("have.text", "cherry"); - - cy.get(cesc2("#/ti1changed")).should("have.text", "true"); - cy.get(cesc2("#/ti2changed")).should("have.text", "true"); - cy.get(cesc2("#/ti3changed")).should("have.text", "false"); - cy.get(cesc2("#/ti4changed")).should("have.text", "false"); - - cy.get(cesc2("#/ti1ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/ti2ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/ti3ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/ti4ivchanged")).should("have.text", "false"); - - cy.log("type in third marks third immediate value as changed"); - - cy.get(cesc2("#/ti3") + "_input") - .clear() - .type("dragonfruit", { - force: true, - }); - - cy.get(cesc2("#/ti3iva")).should("have.text", "dragonfruit"); - - cy.get(cesc2("#/ti1a")).should("have.text", "banana"); - cy.get(cesc2("#/ti2a")).should("have.text", "cherry"); - cy.get(cesc2("#/ti3a")).should("have.text", "banana"); - cy.get(cesc2("#/ti4a")).should("have.text", "cherry"); - - cy.get(cesc2("#/ti1iva")).should("have.text", "banana"); - cy.get(cesc2("#/ti2iva")).should("have.text", "cherry"); - cy.get(cesc2("#/ti3iva")).should("have.text", "dragonfruit"); - cy.get(cesc2("#/ti4iva")).should("have.text", "cherry"); - - cy.get(cesc2("#/ti1changed")).should("have.text", "true"); - cy.get(cesc2("#/ti2changed")).should("have.text", "true"); - cy.get(cesc2("#/ti3changed")).should("have.text", "false"); - cy.get(cesc2("#/ti4changed")).should("have.text", "false"); - - cy.get(cesc2("#/ti1ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/ti2ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/ti3ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/ti4ivchanged")).should("have.text", "false"); - - cy.log("press enter in third marks third value as changed"); - - cy.get(cesc2("#/ti3") + "_input").type("{enter}"); - - cy.get(cesc2("#/ti3a")).should("have.text", "dragonfruit"); - - cy.get(cesc2("#/ti1a")).should("have.text", "dragonfruit"); - cy.get(cesc2("#/ti2a")).should("have.text", "cherry"); - cy.get(cesc2("#/ti3a")).should("have.text", "dragonfruit"); - cy.get(cesc2("#/ti4a")).should("have.text", "cherry"); - - cy.get(cesc2("#/ti1iva")).should("have.text", "dragonfruit"); - cy.get(cesc2("#/ti2iva")).should("have.text", "cherry"); - cy.get(cesc2("#/ti3iva")).should("have.text", "dragonfruit"); - cy.get(cesc2("#/ti4iva")).should("have.text", "cherry"); - - cy.get(cesc2("#/ti1changed")).should("have.text", "true"); - cy.get(cesc2("#/ti2changed")).should("have.text", "true"); - cy.get(cesc2("#/ti3changed")).should("have.text", "true"); - cy.get(cesc2("#/ti4changed")).should("have.text", "false"); - - cy.get(cesc2("#/ti1ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/ti2ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/ti3ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/ti4ivchanged")).should("have.text", "false"); - - cy.log("type in fourth marks fourth immediate value as changed"); - - cy.get(cesc2("#/ti4") + "_input") - .clear() - .type("eggplant", { - force: true, - }); - - cy.get(cesc2("#/ti4iva")).should("have.text", "eggplant"); - - cy.get(cesc2("#/ti1a")).should("have.text", "dragonfruit"); - cy.get(cesc2("#/ti2a")).should("have.text", "cherry"); - cy.get(cesc2("#/ti3a")).should("have.text", "dragonfruit"); - cy.get(cesc2("#/ti4a")).should("have.text", "cherry"); - - cy.get(cesc2("#/ti1iva")).should("have.text", "dragonfruit"); - cy.get(cesc2("#/ti2iva")).should("have.text", "cherry"); - cy.get(cesc2("#/ti3iva")).should("have.text", "dragonfruit"); - cy.get(cesc2("#/ti4iva")).should("have.text", "eggplant"); - - cy.get(cesc2("#/ti1changed")).should("have.text", "true"); - cy.get(cesc2("#/ti2changed")).should("have.text", "true"); - cy.get(cesc2("#/ti3changed")).should("have.text", "true"); - cy.get(cesc2("#/ti4changed")).should("have.text", "false"); - - cy.get(cesc2("#/ti1ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/ti2ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/ti3ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/ti4ivchanged")).should("have.text", "true"); - - cy.log("press enter in fourth marks fourth value as changed"); - - cy.get(cesc2("#/ti4") + "_input").type("{enter}"); - - cy.get(cesc2("#/ti4a")).should("have.text", "eggplant"); - - cy.get(cesc2("#/ti1a")).should("have.text", "dragonfruit"); - cy.get(cesc2("#/ti2a")).should("have.text", "eggplant"); - cy.get(cesc2("#/ti3a")).should("have.text", "dragonfruit"); - cy.get(cesc2("#/ti4a")).should("have.text", "eggplant"); - - cy.get(cesc2("#/ti1iva")).should("have.text", "dragonfruit"); - cy.get(cesc2("#/ti2iva")).should("have.text", "eggplant"); - cy.get(cesc2("#/ti3iva")).should("have.text", "dragonfruit"); - cy.get(cesc2("#/ti4iva")).should("have.text", "eggplant"); - - cy.get(cesc2("#/ti1changed")).should("have.text", "true"); - cy.get(cesc2("#/ti2changed")).should("have.text", "true"); - cy.get(cesc2("#/ti3changed")).should("have.text", "true"); - cy.get(cesc2("#/ti4changed")).should("have.text", "true"); - - cy.get(cesc2("#/ti1ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/ti2ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/ti3ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/ti4ivchanged")).should("have.text", "true"); - - cy.log("reload"); - cy.reload(); - - cy.window().then(async (win) => { - win.postMessage( - { - doenetML, - }, - "*", - ); - }); - - cy.get(cesc2("#/ti1a")).should("have.text", ""); - cy.get(cesc2("#/ti2a")).should("have.text", "apple"); - cy.get(cesc2("#/ti3a")).should("have.text", ""); - cy.get(cesc2("#/ti4a")).should("have.text", "apple"); - - cy.get(cesc2("#/ti1iva")).should("have.text", ""); - cy.get(cesc2("#/ti2iva")).should("have.text", "apple"); - cy.get(cesc2("#/ti3iva")).should("have.text", ""); - cy.get(cesc2("#/ti4iva")).should("have.text", "apple"); - - cy.get(cesc2("#/ti1changed")).should("have.text", "false"); - cy.get(cesc2("#/ti2changed")).should("have.text", "false"); - cy.get(cesc2("#/ti3changed")).should("have.text", "false"); - cy.get(cesc2("#/ti4changed")).should("have.text", "false"); - - cy.get(cesc2("#/ti1ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/ti2ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/ti3ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/ti4ivchanged")).should("have.text", "false"); - - cy.log("type in third marks only third immediate value as changed"); - - cy.get(cesc2("#/ti3") + "_input").type("banana"); - - cy.get(cesc2("#/ti3iva")).should("have.text", "banana"); - - cy.get(cesc2("#/ti1a")).should("have.text", ""); - cy.get(cesc2("#/ti2a")).should("have.text", "apple"); - cy.get(cesc2("#/ti3a")).should("have.text", ""); - cy.get(cesc2("#/ti4a")).should("have.text", "apple"); - - cy.get(cesc2("#/ti1iva")).should("have.text", ""); - cy.get(cesc2("#/ti2iva")).should("have.text", "apple"); - cy.get(cesc2("#/ti3iva")).should("have.text", "banana"); - cy.get(cesc2("#/ti4iva")).should("have.text", "apple"); - - cy.get(cesc2("#/ti1changed")).should("have.text", "false"); - cy.get(cesc2("#/ti2changed")).should("have.text", "false"); - cy.get(cesc2("#/ti3changed")).should("have.text", "false"); - cy.get(cesc2("#/ti4changed")).should("have.text", "false"); - - cy.get(cesc2("#/ti1ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/ti2ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/ti3ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/ti4ivchanged")).should("have.text", "false"); - - cy.log( - "press enter in third marks first and third value/immediateValue as changed", - ); - - cy.get(cesc2("#/ti3") + "_input").type("{enter}"); - - cy.get(cesc2("#/ti3a")).should("have.text", "banana"); - - cy.get(cesc2("#/ti1a")).should("have.text", "banana"); - cy.get(cesc2("#/ti2a")).should("have.text", "apple"); - cy.get(cesc2("#/ti3a")).should("have.text", "banana"); - cy.get(cesc2("#/ti4a")).should("have.text", "apple"); - - cy.get(cesc2("#/ti1iva")).should("have.text", "banana"); - cy.get(cesc2("#/ti2iva")).should("have.text", "apple"); - cy.get(cesc2("#/ti3iva")).should("have.text", "banana"); - cy.get(cesc2("#/ti4iva")).should("have.text", "apple"); - - cy.get(cesc2("#/ti1changed")).should("have.text", "true"); - cy.get(cesc2("#/ti2changed")).should("have.text", "false"); - cy.get(cesc2("#/ti3changed")).should("have.text", "true"); - cy.get(cesc2("#/ti4changed")).should("have.text", "false"); - - cy.get(cesc2("#/ti1ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/ti2ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/ti3ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/ti4ivchanged")).should("have.text", "false"); - - cy.log("type in fourth marks only fourth immediate value as changed"); - - cy.get(cesc2("#/ti4") + "_input") - .clear() - .type("cherry", { - force: true, - }); - - cy.get(cesc2("#/ti4iva")).should("have.text", "cherry"); - - cy.get(cesc2("#/ti1a")).should("have.text", "banana"); - cy.get(cesc2("#/ti2a")).should("have.text", "apple"); - cy.get(cesc2("#/ti3a")).should("have.text", "banana"); - cy.get(cesc2("#/ti4a")).should("have.text", "apple"); - - cy.get(cesc2("#/ti1iva")).should("have.text", "banana"); - cy.get(cesc2("#/ti2iva")).should("have.text", "apple"); - cy.get(cesc2("#/ti3iva")).should("have.text", "banana"); - cy.get(cesc2("#/ti4iva")).should("have.text", "cherry"); - - cy.get(cesc2("#/ti1changed")).should("have.text", "true"); - cy.get(cesc2("#/ti2changed")).should("have.text", "false"); - cy.get(cesc2("#/ti3changed")).should("have.text", "true"); - cy.get(cesc2("#/ti4changed")).should("have.text", "false"); - - cy.get(cesc2("#/ti1ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/ti2ivchanged")).should("have.text", "false"); - cy.get(cesc2("#/ti3ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/ti4ivchanged")).should("have.text", "true"); - - cy.log( - "press enter in fourth marks third and fourth value/immediateValue as changed", - ); - - cy.get(cesc2("#/ti4") + "_input").type("{enter}"); - - cy.get(cesc2("#/ti4a")).should("have.text", "cherry"); - - cy.get(cesc2("#/ti1a")).should("have.text", "banana"); - cy.get(cesc2("#/ti2a")).should("have.text", "cherry"); - cy.get(cesc2("#/ti3a")).should("have.text", "banana"); - cy.get(cesc2("#/ti4a")).should("have.text", "cherry"); - - cy.get(cesc2("#/ti1iva")).should("have.text", "banana"); - cy.get(cesc2("#/ti2iva")).should("have.text", "cherry"); - cy.get(cesc2("#/ti3iva")).should("have.text", "banana"); - cy.get(cesc2("#/ti4iva")).should("have.text", "cherry"); - - cy.get(cesc2("#/ti1changed")).should("have.text", "true"); - cy.get(cesc2("#/ti2changed")).should("have.text", "true"); - cy.get(cesc2("#/ti3changed")).should("have.text", "true"); - cy.get(cesc2("#/ti4changed")).should("have.text", "true"); - - cy.get(cesc2("#/ti1ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/ti2ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/ti3ivchanged")).should("have.text", "true"); - cy.get(cesc2("#/ti4ivchanged")).should("have.text", "true"); - }); - - it("text input with label", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

-

- - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/ti1")).should("have.text", "Type something"); - cy.get(cesc2("#/ti2")).should("contain.text", "Hello"); - cy.get(cesc2("#/ti2") + " .mjx-mrow") - .eq(0) - .should("have.text", "ab"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/ti1"].stateValues.label).eq( - "Type something", - ); - expect(stateVariables["/ti2"].stateValues.label).eq( - "Hello \\(\\frac{a}{b}\\)", - ); - }); - }); }); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/triggerset.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/triggerset.cy.js deleted file mode 100644 index 0474158a5..000000000 --- a/packages/test-cypress/cypress/e2e/tagSpecific/triggerset.cy.js +++ /dev/null @@ -1,2056 +0,0 @@ -import { cesc } from "@doenet/utils"; - -describe("TriggerSet Tag Tests", function () { - beforeEach(() => { - cy.clearIndexedDB(); - cy.visit("/"); - }); - - it("triggerSet", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Boolean to swap:

-

Say hello:

-

Count: 1

- - - (1,2) - - -

- - - - - - - - - - - - (3,4) - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/flip")).should("not.exist"); - cy.get(cesc("#\\/addHello")).should("not.exist"); - cy.get(cesc("#\\/addOne")).should("not.exist"); - cy.get(cesc("#\\/rs")).should("not.exist"); - cy.get(cesc("#\\/addPoint")).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let numbers; - let g = stateVariables["/g"]; - - expect(g.activeChildren.length).eq(1); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - numbers = text.split(",").map(Number); - expect(numbers.length).eq(5); - for (let num of numbers) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - }); - - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", ""); - cy.get(cesc("#\\/n")).should("have.text", "1"); - - cy.get(cesc("#\\/tset_button")).click(); - cy.waitUntil(() => - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - return g.activeChildren.length === 2; - }), - ); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).not.eqls(numbers); - numbers = numbers2; - }); - - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "2"); - - cy.get(cesc("#\\/tset_button")).click(); - cy.waitUntil(() => - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - return g.activeChildren.length === 3; - }), - ); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).not.eqls(numbers); - numbers = numbers2; - }); - - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", " hello hello"); - cy.get(cesc("#\\/n")).should("have.text", "3"); - - cy.get(cesc("#\\/tset_button")).click(); - cy.waitUntil(() => - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - return g.activeChildren.length === 4; - }), - ); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).not.eqls(numbers); - numbers = numbers2; - }); - - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello hello hello"); - cy.get(cesc("#\\/n")).should("have.text", "4"); - }); - }); - - it("triggerSet and chain to updatevalue and call action", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Boolean to swap:

-

Say hello:

-

Count: 1

- - - (1,2) - - -

- - - - - - - - - - - - - - (3,4) - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/flip")).should("not.exist"); - cy.get(cesc("#\\/addHello")).should("not.exist"); - cy.get(cesc("#\\/addOne")).should("not.exist"); - cy.get(cesc("#\\/rs")).should("not.exist"); - cy.get(cesc("#\\/addPoint")).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let numbers; - let g = stateVariables["/g"]; - - expect(g.activeChildren.length).eq(1); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - numbers = text.split(",").map(Number); - expect(numbers.length).eq(5); - for (let num of numbers) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - }); - - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", ""); - cy.get(cesc("#\\/n")).should("have.text", "1"); - - cy.get(cesc("#\\/tset_button")).click(); - cy.waitUntil(() => - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - return g.activeChildren.length === 2; - }), - ); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).not.eqls(numbers); - numbers = numbers2; - }); - - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "2"); - - cy.get(cesc("#\\/tset_button")).click(); - cy.waitUntil(() => - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - return g.activeChildren.length === 3; - }), - ); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).not.eqls(numbers); - numbers = numbers2; - }); - - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", " hello hello"); - cy.get(cesc("#\\/n")).should("have.text", "3"); - - cy.get(cesc("#\\/tset_button")).click(); - cy.waitUntil(() => - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - return g.activeChildren.length === 4; - }), - ); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).not.eqls(numbers); - numbers = numbers2; - }); - - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello hello hello"); - cy.get(cesc("#\\/n")).should("have.text", "4"); - }); - }); - - it("triggerSet and chain to triggerset", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Boolean to swap:

-

Say hello:

-

Count: 1

- - - (1,2) - - -

- - - - - - - - - - - - - - - - (3,4) - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/flip")).should("not.exist"); - cy.get(cesc("#\\/addHello")).should("not.exist"); - cy.get(cesc("#\\/addOne")).should("not.exist"); - cy.get(cesc("#\\/rs")).should("not.exist"); - cy.get(cesc("#\\/addPoint")).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let numbers; - let g = stateVariables["/g"]; - - expect(g.activeChildren.length).eq(1); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - numbers = text.split(",").map(Number); - expect(numbers.length).eq(5); - for (let num of numbers) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - }); - - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", ""); - cy.get(cesc("#\\/n")).should("have.text", "1"); - - cy.get(cesc("#\\/tset_button")).click(); - cy.waitUntil(() => - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - return g.activeChildren.length === 2; - }), - ); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).not.eqls(numbers); - numbers = numbers2; - }); - - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "2"); - - cy.get(cesc("#\\/tset_button")).click(); - cy.waitUntil(() => - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - return g.activeChildren.length === 3; - }), - ); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).not.eqls(numbers); - numbers = numbers2; - }); - - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", " hello hello"); - cy.get(cesc("#\\/n")).should("have.text", "3"); - - cy.get(cesc("#\\/tset_button")).click(); - cy.waitUntil(() => - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - return g.activeChildren.length === 4; - }), - ); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).not.eqls(numbers); - numbers = numbers2; - }); - - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello hello hello"); - cy.get(cesc("#\\/n")).should("have.text", "4"); - }); - }); - - it("triggerSet and chain multiple sources to triggerset", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Boolean to swap:

-

Say hello:

-

Count: 1

-

Count 2: 1

- - - (1,2) - - -

- - - - - - - - - - - - - - - - (3,4) - - - - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/flip")).should("not.exist"); - cy.get(cesc("#\\/addHello")).should("not.exist"); - cy.get(cesc("#\\/addOne")).should("not.exist"); - cy.get(cesc("#\\/rs")).should("not.exist"); - cy.get(cesc("#\\/addPoint")).should("not.exist"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let numbers; - let g = stateVariables["/g"]; - - expect(g.activeChildren.length).eq(1); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - numbers = text.split(",").map(Number); - expect(numbers.length).eq(5); - for (let num of numbers) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - }); - - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", ""); - cy.get(cesc("#\\/n")).should("have.text", "1"); - cy.get(cesc("#\\/n2")).should("have.text", "1"); - - cy.get(cesc("#\\/tset_button")).click(); - cy.waitUntil(() => - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - return g.activeChildren.length === 2; - }), - ); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).not.eqls(numbers); - numbers = numbers2; - }); - - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "2"); - cy.get(cesc("#\\/n2")).should("have.text", "1"); - - cy.get(cesc("#\\/in_button")).click(); - cy.waitUntil(() => - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - return g.activeChildren.length === 3; - }), - ); - - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "3"); - cy.get(cesc("#\\/n2")).should("have.text", "2"); - }); - }); - - it("triggerSet based on trigger", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (-1,2) - - x - y - - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - - cy.get(cesc("#\\/trip")).should("not.exist"); - cy.get(cesc("#\\/quad")).should("not.exist"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -1, y: -7 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 3, y: -4 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 1, y: 7 }, - }); - cy.get(cesc("#\\/x")).should("contain.text", "3x"); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 5, y: 9 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -3, y: 4 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -6, y: 5 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 4, y: 2 }, - }); - cy.get(cesc("#\\/x")).should("contain.text", "9x"); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("16y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 9, y: 7 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("16y"); - }); - }); - }); - - it("triggerSet triggered when click", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (-1,2) - - x - y - - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - - cy.get(cesc("#\\/trip")).should("not.exist"); - cy.get(cesc("#\\/quad")).should("not.exist"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -1, y: -7 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "pointClicked", - componentName: "/P", - args: { name: "/P" }, - }); - cy.get(cesc("#\\/x")).should("contain.text", "3x"); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 5, y: 9 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "pointClicked", - componentName: "/P", - args: { name: "/P" }, - }); - cy.get(cesc("#\\/x")).should("contain.text", "9x"); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("16y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 9, y: 7 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("16y"); - }); - }); - }); - - it("triggerSet triggered when object focused", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (-1,2) - - x - y - - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - - cy.get(cesc("#\\/trip")).should("not.exist"); - cy.get(cesc("#\\/quad")).should("not.exist"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -1, y: -7 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "pointFocused", - componentName: "/P", - args: { name: "/P" }, - }); - cy.get(cesc("#\\/x")).should("contain.text", "3x"); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 5, y: 9 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "pointFocused", - componentName: "/P", - args: { name: "/P" }, - }); - cy.get(cesc("#\\/x")).should("contain.text", "9x"); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("16y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 9, y: 7 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("16y"); - }); - }); - }); - - it("triggerWhen supercedes chaining for triggerset", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (-1,2) - - -

Boolean to swap:

-

Say hello:

-

Count: 1

-

Count down: 5

- - - - - - - - - - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", ""); - cy.get(cesc("#\\/n")).should("have.text", "1"); - cy.get(cesc("#\\/m")).should("have.text", "5"); - cy.get(cesc("#\\/_triggerset1")).should("not.exist"); - cy.get(cesc("#\\/_triggerset2")).should("not.exist"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -1, y: -7 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", ""); - cy.get(cesc("#\\/n")).should("have.text", "2"); - cy.get(cesc("#\\/m")).should("have.text", "4"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 3, y: -4 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", ""); - cy.get(cesc("#\\/n")).should("have.text", "2"); - cy.get(cesc("#\\/m")).should("have.text", "4"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 1, y: 7 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "2"); - cy.get(cesc("#\\/m")).should("have.text", "4"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 5, y: 9 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "2"); - cy.get(cesc("#\\/m")).should("have.text", "4"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -3, y: -4 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "3"); - cy.get(cesc("#\\/m")).should("have.text", "3"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -6, y: -5 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "3"); - cy.get(cesc("#\\/m")).should("have.text", "3"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 4, y: 2 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", " hello hello"); - cy.get(cesc("#\\/n")).should("have.text", "3"); - cy.get(cesc("#\\/m")).should("have.text", "3"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 9, y: 7 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", " hello hello"); - cy.get(cesc("#\\/n")).should("have.text", "3"); - cy.get(cesc("#\\/m")).should("have.text", "3"); - }); - }); - - it("triggerset supercedes triggerWhen for updateValue and callAction children", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (-1,2) - - -

Boolean to swap:

-

Say hello:

-

Count: 1

- -

- - - - - - - - - - - - (3,4) - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let numbers; - let g = stateVariables["/g"]; - - expect(g.activeChildren.length).eq(1); - - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - numbers = text.split(",").map(Number); - expect(numbers.length).eq(5); - for (let num of numbers) { - expect(Number.isInteger(num)).be.true; - expect(num).gte(1); - expect(num).lte(6); - } - }); - - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", ""); - cy.get(cesc("#\\/n")).should("have.text", "1"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -1, y: -7 }, - }); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.activeChildren.length).eq(1); - }); - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", ""); - cy.get(cesc("#\\/n")).should("have.text", "1"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 3, y: -4 }, - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.activeChildren.length).eq(1); - }); - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", ""); - cy.get(cesc("#\\/n")).should("have.text", "1"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 1, y: 7 }, - }); - - cy.waitUntil(() => - cy.window().then(async (win) => { - let stateVariables = - await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - return g.activeChildren.length === 2; - }), - ); - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).not.eqls(numbers); - numbers = numbers2; - }); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "2"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 5, y: 9 }, - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.activeChildren.length).eq(2); - }); - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "2"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -3, y: -4 }, - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.activeChildren.length).eq(2); - }); - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "2"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -6, y: -5 }, - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.activeChildren.length).eq(2); - }); - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "2"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 4, y: 2 }, - }); - - cy.waitUntil(() => - cy.window().then(async (win) => { - let stateVariables = - await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - return g.activeChildren.length === 3; - }), - ); - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).not.eqls(numbers); - numbers = numbers2; - }); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", " hello hello"); - cy.get(cesc("#\\/n")).should("have.text", "3"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 9, y: 7 }, - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.activeChildren.length).eq(3); - }); - cy.get(cesc("#\\/nums")) - .invoke("text") - .then((text) => { - let numbers2 = text.split(",").map(Number); - expect(numbers2).eqls(numbers); - }); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", " hello hello"); - cy.get(cesc("#\\/n")).should("have.text", "3"); - }); - }); - }); - - it("triggerset supercedes chaining for updateValue children", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (-1,2) - - -

Boolean to swap:

-

Say hello:

-

Count: 1

-

Count down: 5

- - - - - - - - - (3,4) - - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - - expect(g.activeChildren.length).eq(1); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", ""); - cy.get(cesc("#\\/n")).should("have.text", "1"); - cy.get(cesc("#\\/m")).should("have.text", "5"); - cy.get(cesc("#\\/_triggerset1")).should("not.exist"); - cy.get(cesc("#\\/uv")).should("not.exist"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -1, y: -7 }, - }); - cy.get(cesc("#\\/m")).should("have.text", "4"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.activeChildren.length).eq(1); - }); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", ""); - cy.get(cesc("#\\/n")).should("have.text", "1"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 3, y: -4 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", ""); - cy.get(cesc("#\\/n")).should("have.text", "1"); - cy.get(cesc("#\\/m")).should("have.text", "4"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 1, y: 7 }, - }); - - cy.waitUntil(() => - cy.window().then(async (win) => { - let stateVariables = - await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - return g.activeChildren.length === 2; - }), - ); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "2"); - cy.get(cesc("#\\/m")).should("have.text", "4"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 5, y: 9 }, - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.activeChildren.length).eq(2); - }); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "2"); - cy.get(cesc("#\\/m")).should("have.text", "4"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -3, y: -4 }, - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.activeChildren.length).eq(2); - }); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "2"); - cy.get(cesc("#\\/m")).should("have.text", "3"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -6, y: -5 }, - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.activeChildren.length).eq(2); - }); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "2"); - cy.get(cesc("#\\/m")).should("have.text", "3"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 4, y: 2 }, - }); - cy.waitUntil(() => - cy.window().then(async (win) => { - let stateVariables = - await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - return g.activeChildren.length === 3; - }), - ); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", " hello hello"); - cy.get(cesc("#\\/n")).should("have.text", "3"); - cy.get(cesc("#\\/m")).should("have.text", "3"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 9, y: 7 }, - }); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let g = stateVariables["/g"]; - expect(g.activeChildren.length).eq(3); - }); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", " hello hello"); - cy.get(cesc("#\\/n")).should("have.text", "3"); - cy.get(cesc("#\\/m")).should("have.text", "3"); - }); - }); - }); - - it("triggerSet with math in label", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Boolean to swap:

- - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/tset")).should("contain.text", "It is ∂f∂x"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/tset"].stateValues.label).eq( - "It is \\(\\frac{ \\partial f }{ \\partial x }\\)", - ); - }); - }); - - it("triggerSet with label is name", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Boolean to swap:

- - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/trigger-me")).should("contain.text", "trigger me"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/trigger-me"].stateValues.label).eq( - "trigger me", - ); - }); - }); - - it("triggerset in graph", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

n: 1

- - - - - (3,4) - - - - - - - (-3,-4) - - - - - - -

Anchor 1 coordinates: $triggerset1.anchor

-

Anchor 2 coordinates: $triggerset2.anchor

-

Change anchor 1 coordinates:

-

Change anchor 2 coordinates:

-

Position from anchor 1: $triggerset1.positionFromAnchor

-

Position from anchor 2: $triggerset2.positionFromAnchor

-

Change position from anchor 1 - - upperRight - upperLeft - lowerRight - lowerLeft - left - right - top - bottom - center - -

-

Change position from anchor 2 - - upperRight - upperLeft - lowerRight - lowerLeft - left - right - top - bottom - center - -

-

Draggable 1: $draggable1

-

Draggable 2: $draggable2

-

Change draggable 1

-

Change draggable 2

-

Disabled 1: $disabled1

-

Disabled 2: $disabled2

-

Change disabled 1

-

Change disabled 2

-

Fixed 1: $fixed1

-

Fixed 2: $fixed2

-

Change fixed 1

-

Change fixed 2

-

FixLocation 1: $fixLocation1

-

FixLocation 2: $fixLocation2

-

Change fixLocation 1

-

Change fixLocation 2

-

- - `, - }, - "*", - ); - }); - - // TODO: how to click on the buttons and test if they are disabled? - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,3)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,0)"); - - cy.get(cesc("#\\/pPositionFromAnchor1")).should( - "have.text", - "Position from anchor 1: upperright", - ); - cy.get(cesc("#\\/pPositionFromAnchor2")).should( - "have.text", - "Position from anchor 2: center", - ); - cy.get(cesc("#\\/positionFromAnchor1")).should("have.value", "1"); - cy.get(cesc("#\\/positionFromAnchor2")).should("have.value", "9"); - cy.get(cesc("#\\/pDraggable1")).should( - "have.text", - "Draggable 1: true", - ); - cy.get(cesc("#\\/pDraggable2")).should( - "have.text", - "Draggable 2: true", - ); - - cy.log("move triggersets by dragging"); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveButton", - componentName: "/triggerset1", - args: { x: -2, y: 3 }, - }); - win.callAction1({ - actionName: "moveButton", - componentName: "/triggerset2", - args: { x: 4, y: -5 }, - }); - }); - - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow").should( - "contain.text", - "(4,−5)", - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−2,3)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(4,−5)"); - - cy.log("move triggersets by entering coordinates"); - - cy.get(cesc("#\\/anchorCoords1") + " textarea").type( - "{home}{shift+end}{backspace}(6,7){enter}", - { force: true }, - ); - cy.get(cesc("#\\/anchorCoords2") + " textarea").type( - "{home}{shift+end}{backspace}(8,9){enter}", - { force: true }, - ); - - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow").should( - "contain.text", - "(8,9)", - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(6,7)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(8,9)"); - - cy.log("change position from anchor"); - cy.get(cesc("#\\/positionFromAnchor1")).select("lowerLeft"); - cy.get(cesc("#\\/positionFromAnchor2")).select("lowerRight"); - - cy.get(cesc("#\\/pPositionFromAnchor1")).should( - "have.text", - "Position from anchor 1: lowerleft", - ); - cy.get(cesc("#\\/pPositionFromAnchor2")).should( - "have.text", - "Position from anchor 2: lowerright", - ); - - cy.log("make not draggable"); - - cy.get(cesc("#\\/draggable1")).click(); - cy.get(cesc("#\\/draggable2")).click(); - cy.get(cesc("#\\/pDraggable1")).should( - "have.text", - "Draggable 1: false", - ); - cy.get(cesc("#\\/pDraggable2")).should( - "have.text", - "Draggable 2: false", - ); - - cy.log("cannot move triggersets by dragging"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveButton", - componentName: "/triggerset1", - args: { x: -10, y: -9 }, - }); - win.callAction1({ - actionName: "moveButton", - componentName: "/triggerset2", - args: { x: -8, y: -7 }, - }); - }); - - // since nothing will change, wait for boolean input to change to know core has responded - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/b")).should("have.text", "true"); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(6,7)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(8,9)"); - - cy.log("make draggable again"); - - cy.get(cesc("#\\/draggable1")).click(); - cy.get(cesc("#\\/draggable2")).click(); - cy.get(cesc("#\\/pDraggable1")).should( - "have.text", - "Draggable 1: true", - ); - cy.get(cesc("#\\/pDraggable2")).should( - "have.text", - "Draggable 2: true", - ); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveButton", - componentName: "/triggerset1", - args: { x: -10, y: -9 }, - }); - win.callAction1({ - actionName: "moveButton", - componentName: "/triggerset2", - args: { x: -8, y: -7 }, - }); - }); - - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow").should( - "contain.text", - "(−8,−7)", - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−10,−9)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−8,−7)"); - - cy.log("fix location"); - - cy.get(cesc("#\\/fixLocation1")).click(); - cy.get(cesc("#\\/fixLocation2")).click(); - cy.get(cesc("#\\/pFixLocation1")).should( - "have.text", - "FixLocation 1: true", - ); - cy.get(cesc("#\\/pFixLocation2")).should( - "have.text", - "FixLocation 2: true", - ); - - cy.log("can change coordinates entering coordinates only for button 1"); - - cy.get(cesc("#\\/anchorCoords2") + " textarea").type( - "{home}{shift+end}{backspace}(3,4){enter}", - { force: true }, - ); - cy.get(cesc("#\\/anchorCoords1") + " textarea").type( - "{home}{shift+end}{backspace}(1,2){enter}", - { force: true }, - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow").should( - "contain.text", - "(1,2)", - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−8,−7)"); - - cy.log("cannot move triggersets by dragging"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveButton", - componentName: "/triggerset1", - args: { x: 4, y: 6 }, - }); - win.callAction1({ - actionName: "moveButton", - componentName: "/triggerset2", - args: { x: 7, y: 8 }, - }); - }); - - // since nothing will change, wait for boolean input to change to know core has responded - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/b")).should("have.text", "false"); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−8,−7)"); - - cy.log("can change position from anchor only for button 1"); - cy.get(cesc("#\\/positionFromAnchor2")).select("bottom"); - cy.get(cesc("#\\/positionFromAnchor1")).select("top"); - - cy.get(cesc("#\\/pPositionFromAnchor1")).should( - "have.text", - "Position from anchor 1: top", - ); - cy.get(cesc("#\\/pPositionFromAnchor2")).should( - "have.text", - "Position from anchor 2: lowerright", - ); - - cy.log("can change disabled attribute"); - cy.get(cesc("#\\/disabled1")).click(); - cy.get(cesc("#\\/disabled2")).click(); - cy.get(cesc("#\\/pDisabled1")).should("have.text", "Disabled 1: false"); - cy.get(cesc("#\\/pDisabled2")).should("have.text", "Disabled 2: true"); - - cy.log("make completely fixed"); - cy.get(cesc("#\\/fixed1")).click(); - cy.get(cesc("#\\/fixed2")).click(); - cy.get(cesc("#\\/pFixed1")).should("have.text", "Fixed 1: true"); - cy.get(cesc("#\\/pFixed2")).should("have.text", "Fixed 2: true"); - - cy.log("can change coordinates entering coordinates only for button 1"); - - cy.get(cesc("#\\/anchorCoords2") + " textarea").type( - "{home}{shift+end}{backspace}(7,8){enter}", - { force: true }, - ); - cy.get(cesc("#\\/anchorCoords1") + " textarea").type( - "{home}{shift+end}{backspace}(5,6){enter}", - { force: true }, - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow").should( - "contain.text", - "(5,6)", - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(5,6)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−8,−7)"); - - cy.log("can change position from anchor only for button 1"); - cy.get(cesc("#\\/positionFromAnchor2")).select("left"); - cy.get(cesc("#\\/positionFromAnchor1")).select("right"); - - cy.get(cesc("#\\/pPositionFromAnchor1")).should( - "have.text", - "Position from anchor 1: right", - ); - cy.get(cesc("#\\/pPositionFromAnchor2")).should( - "have.text", - "Position from anchor 2: lowerright", - ); - - cy.log("can change disabled attribute only for button 1"); - cy.get(cesc("#\\/disabled2")).click(); - cy.get(cesc("#\\/disabled1")).click(); - cy.get(cesc("#\\/pDisabled1")).should("have.text", "Disabled 1: true"); - cy.get(cesc("#\\/pDisabled2")).should("have.text", "Disabled 2: true"); - }); -}); diff --git a/packages/test-cypress/cypress/e2e/tagSpecific/updatevalue.cy.js b/packages/test-cypress/cypress/e2e/tagSpecific/updatevalue.cy.js index ad8d9e8c6..61431b1ba 100644 --- a/packages/test-cypress/cypress/e2e/tagSpecific/updatevalue.cy.js +++ b/packages/test-cypress/cypress/e2e/tagSpecific/updatevalue.cy.js @@ -7,3169 +7,6 @@ describe("UpdateValue Tag Tests", function () { cy.visit("/"); }); - it("incrementing graph of line segments", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 20/$count - 2 - - - - - - - - -

- - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - let left = -10; - - cy.log(`check internal values`); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let count = 2; - let step = 20 / count; - - expect(stateVariables["/count"].stateValues.value).eq(count); - expect(stateVariables["/step"].stateValues.value).eq(step); - - for (let ind = 1; ind <= count; ind++) { - expect( - me - .fromAst( - stateVariables["/l" + ind + "/_linesegment1"] - .stateValues.endpoints[0][0], - ) - .evaluate_to_constant(), - ).closeTo(left + (ind - 1) * step, 1e-12); - expect( - me - .fromAst( - stateVariables["/l" + ind + "/_linesegment1"] - .stateValues.endpoints[0][1], - ) - .evaluate_to_constant(), - ).closeTo(Math.sin(left + (ind - 1) * step), 1e-12); - expect( - me - .fromAst( - stateVariables["/l" + ind + "/_linesegment1"] - .stateValues.endpoints[1][0], - ) - .evaluate_to_constant(), - ).closeTo(left + ind * step, 1e-12); - expect( - me - .fromAst( - stateVariables["/l" + ind + "/_linesegment1"] - .stateValues.endpoints[1][1], - ) - .evaluate_to_constant(), - ).closeTo(Math.sin(left + ind * step), 1e-12); - } - }); - - cy.log("double number"); - cy.get(cesc("#\\/_updatevalue1_button")).click(); - cy.get(cesc("#\\/count")).should("have.text", "4"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let count = 4; - let step = 20 / count; - - expect(stateVariables["/count"].stateValues.value).eq(count); - expect(stateVariables["/step"].stateValues.value).eq(step); - - for (let ind = 1; ind <= count; ind++) { - expect( - me - .fromAst( - stateVariables["/l" + ind + "/_linesegment1"] - .stateValues.endpoints[0][0], - ) - .evaluate_to_constant(), - ).closeTo(left + (ind - 1) * step, 1e-12); - expect( - me - .fromAst( - stateVariables["/l" + ind + "/_linesegment1"] - .stateValues.endpoints[0][1], - ) - .evaluate_to_constant(), - ).closeTo(Math.sin(left + (ind - 1) * step), 1e-12); - expect( - me - .fromAst( - stateVariables["/l" + ind + "/_linesegment1"] - .stateValues.endpoints[1][0], - ) - .evaluate_to_constant(), - ).closeTo(left + ind * step, 1e-12); - expect( - me - .fromAst( - stateVariables["/l" + ind + "/_linesegment1"] - .stateValues.endpoints[1][1], - ) - .evaluate_to_constant(), - ).closeTo(Math.sin(left + ind * step), 1e-12); - } - }); - - cy.log("double number a second time"); - cy.get(cesc("#\\/_updatevalue1_button")).click(); - cy.get(cesc("#\\/count")).should("have.text", "8"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let count = 8; - let step = 20 / count; - - expect(stateVariables["/count"].stateValues.value).eq(count); - expect(stateVariables["/step"].stateValues.value).eq(step); - - for (let ind = 1; ind <= count; ind++) { - expect( - me - .fromAst( - stateVariables["/l" + ind + "/_linesegment1"] - .stateValues.endpoints[0][0], - ) - .evaluate_to_constant(), - ).closeTo(left + (ind - 1) * step, 1e-12); - expect( - me - .fromAst( - stateVariables["/l" + ind + "/_linesegment1"] - .stateValues.endpoints[0][1], - ) - .evaluate_to_constant(), - ).closeTo(Math.sin(left + (ind - 1) * step), 1e-12); - expect( - me - .fromAst( - stateVariables["/l" + ind + "/_linesegment1"] - .stateValues.endpoints[1][0], - ) - .evaluate_to_constant(), - ).closeTo(left + ind * step, 1e-12); - expect( - me - .fromAst( - stateVariables["/l" + ind + "/_linesegment1"] - .stateValues.endpoints[1][1], - ) - .evaluate_to_constant(), - ).closeTo(Math.sin(left + ind * step), 1e-12); - } - }); - - cy.log("double number a third time"); - cy.get(cesc("#\\/_updatevalue1_button")).click(); - cy.get(cesc("#\\/count")).should("have.text", "16"); - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - - let count = 16; - let step = 20 / count; - - expect(stateVariables["/count"].stateValues.value).eq(count); - expect(stateVariables["/step"].stateValues.value).eq(step); - - for (let ind = 1; ind <= count; ind++) { - expect( - me - .fromAst( - stateVariables["/l" + ind + "/_linesegment1"] - .stateValues.endpoints[0][0], - ) - .evaluate_to_constant(), - ).closeTo(left + (ind - 1) * step, 1e-12); - expect( - me - .fromAst( - stateVariables["/l" + ind + "/_linesegment1"] - .stateValues.endpoints[0][1], - ) - .evaluate_to_constant(), - ).closeTo(Math.sin(left + (ind - 1) * step), 1e-12); - expect( - me - .fromAst( - stateVariables["/l" + ind + "/_linesegment1"] - .stateValues.endpoints[1][0], - ) - .evaluate_to_constant(), - ).closeTo(left + ind * step, 1e-12); - expect( - me - .fromAst( - stateVariables["/l" + ind + "/_linesegment1"] - .stateValues.endpoints[1][1], - ) - .evaluate_to_constant(), - ).closeTo(Math.sin(left + ind * step), 1e-12); - } - }); - }); - - it("update boolean", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/b")).should("have.text", "false"); - - cy.get(cesc("#\\/_updatevalue1_button")).click(); - cy.get(cesc("#\\/b")).should("have.text", "true"); - - cy.get(cesc("#\\/_updatevalue1_button")).click(); - cy.get(cesc("#\\/b")).should("have.text", "false"); - }); - - // catch bug where componentWithSelectableType wasn't - // converting strings to booleans correctly - it("update boolean using string value", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/b")).should("have.text", "false"); - - cy.get(cesc("#\\/setTrue_button")).click(); - cy.get(cesc("#\\/b")).should("have.text", "true"); - - cy.get(cesc("#\\/setTrue_button")).click(); - cy.get(cesc("#\\/b")).should("have.text", "true"); - - cy.get(cesc("#\\/setFalse_button")).click(); - cy.get(cesc("#\\/b")).should("have.text", "false"); - - cy.get(cesc("#\\/setFalse_button")).click(); - cy.get(cesc("#\\/b")).should("have.text", "false"); - - cy.get(cesc("#\\/setTrue_button")).click(); - cy.get(cesc("#\\/b")).should("have.text", "true"); - }); - - it("update number using string value with operator", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - 1 - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/n")).should("have.text", "1"); - - cy.get(cesc("#\\/setToSum_button")).click(); - cy.get(cesc("#\\/n")).should("have.text", "2"); - }); - - it("update property", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - (1,2) - - - - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/P")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,2)"); - }); - - cy.get(cesc("#\\/_updatevalue1_button")).click(); - cy.waitUntil(() => - cy - .get(cesc("#\\/P")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => text.trim() === "(2,2)"), - ); - - cy.get(cesc("#\\/_updatevalue2_button")).click(); - cy.waitUntil(() => - cy - .get(cesc("#\\/P")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => text.trim() === "(4,2)"), - ); - }); - - it("update componentIndex", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (3,2) - (1,5) - (7,0) - - - - - - -

$bi.value{assignNames="b"}

- `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/p")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2)"); - }); - cy.get(cesc("#\\/p2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,5)"); - }); - cy.get(cesc("#\\/p3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(7,0)"); - }); - - cy.get(cesc("#\\/_updatevalue1_button")).click(); - cy.waitUntil(() => - cy - .get(cesc("#\\/p2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => text.trim() === "(6,5)"), - ); - cy.get(cesc("#\\/p")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2)"); - }); - cy.get(cesc("#\\/p2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(6,5)"); - }); - cy.get(cesc("#\\/p3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(7,0)"); - }); - - cy.get(cesc("#\\/_updatevalue1_button")).click(); - // nothing has changed even after wait for core to respond to booleaninput - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/p")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2)"); - }); - cy.get(cesc("#\\/p2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(6,5)"); - }); - cy.get(cesc("#\\/p3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(7,0)"); - }); - - cy.get(cesc("#\\/_updatevalue2_button")).click(); - cy.waitUntil(() => - cy - .get(cesc("#\\/p2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => text.trim() === "(6,5)"), - ); - cy.get(cesc("#\\/p")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2)"); - }); - cy.get(cesc("#\\/p2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(6,5)"); - }); - cy.get(cesc("#\\/p3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(6,0)"); - }); - - cy.get(cesc("#\\/_updatevalue2_button")).click(); - // nothing has changed even after wait for core to respond to booleaninput - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/p")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2)"); - }); - cy.get(cesc("#\\/p2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(6,5)"); - }); - cy.get(cesc("#\\/p3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(6,0)"); - }); - }); - - it("update componentIndex of group", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (3,2) - ignore me - (1,5) - ignore me too - (7,0) - - - - - -

$bi.value{assignNames="b"}

- `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/p")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2)"); - }); - cy.get(cesc("#\\/p2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,5)"); - }); - cy.get(cesc("#\\/p3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(7,0)"); - }); - - cy.get(cesc("#\\/_updatevalue1_button")).click(); - cy.waitUntil(() => - cy - .get(cesc("#\\/p2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => text.trim() === "(6,5)"), - ); - cy.get(cesc("#\\/p")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2)"); - }); - cy.get(cesc("#\\/p2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(6,5)"); - }); - cy.get(cesc("#\\/p3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(7,0)"); - }); - - cy.get(cesc("#\\/_updatevalue1_button")).click(); - // nothing has changed even after wait for core to respond to booleaninput - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/p")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2)"); - }); - cy.get(cesc("#\\/p2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(6,5)"); - }); - cy.get(cesc("#\\/p3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(7,0)"); - }); - - cy.get(cesc("#\\/_updatevalue2_button")).click(); - cy.waitUntil(() => - cy - .get(cesc("#\\/p2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => text.trim() === "(6,5)"), - ); - cy.get(cesc("#\\/p")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2)"); - }); - cy.get(cesc("#\\/p2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(6,5)"); - }); - cy.get(cesc("#\\/p3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(6,0)"); - }); - - cy.get(cesc("#\\/_updatevalue2_button")).click(); - // nothing has changed even after wait for core to respond to booleaninput - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/p")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2)"); - }); - cy.get(cesc("#\\/p2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(6,5)"); - }); - cy.get(cesc("#\\/p3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(6,0)"); - }); - }); - - it("update componentIndex of group with target subnames", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - -

Number 1 and point (3,2).

-

Text hello and line .

-
- - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc2("#/_p1")).should("contain.text", "Number 1 and"); - cy.get(cesc2("#/_p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,2)"); - cy.get(cesc2("#/_p2")).should("contain.text", "Text hello and"); - cy.get(cesc2("#/_p2") + " .mjx-mrow") - .eq(0) - .should("have.text", "0=x−y+1"); - - cy.get(cesc2("#/_updatevalue1_button")).click(); - cy.get(cesc2("#/_p1")).should("contain.text", "Number 3 and"); - - cy.get(cesc2("#/_updatevalue2_button")).click(); - cy.get(cesc2("#/_p1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,5)"); - - cy.get(cesc2("#/_updatevalue3_button")).click(); - cy.get(cesc2("#/_p2")).should("contain.text", "Text bye and"); - - cy.get(cesc2("#/_updatevalue4_button")).click(); - cy.get(cesc2("#/_p2") + " .mjx-mrow") - .eq(0) - .should("have.text", "0=x−2"); - }); - - it("update propIndex", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - (3,2,1) - - - - - -

$bi.value{assignNames="b"}

- `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/p")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2,1)"); - }); - - cy.get(cesc("#\\/_updatevalue1_button")).click(); - cy.waitUntil(() => - cy - .get(cesc("#\\/p")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => text.trim() === "(3,6,1)"), - ); - - cy.get(cesc("#\\/_updatevalue1_button")).click(); - // nothing has changed even after wait for core to respond to booleaninput - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/p")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,6,1)"); - }); - - cy.get(cesc("#\\/_updatevalue2_button")).click(); - cy.waitUntil(() => - cy - .get(cesc("#\\/p")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => text.trim() === "(3,6,6)"), - ); - - cy.get(cesc("#\\/_updatevalue2_button")).click(); - // nothing has changed even after wait for core to respond to booleaninput - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/p")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,6,6)"); - }); - }); - - it("update multiple components", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (3,2) - (1,5) - (7,0) - - - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/p")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(3,2)"); - }); - cy.get(cesc("#\\/p2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,5)"); - }); - cy.get(cesc("#\\/p3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(7,0)"); - }); - - cy.get(cesc("#\\/_updatevalue1_button")).click(); - cy.waitUntil(() => - cy - .get(cesc("#\\/p")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => text.trim() === "(6,2)"), - ); - cy.get(cesc("#\\/p")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(6,2)"); - }); - cy.get(cesc("#\\/p2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(6,5)"); - }); - cy.get(cesc("#\\/p3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(6,0)"); - }); - - cy.get(cesc("#\\/_updatevalue2_button")).click(); - cy.waitUntil(() => - cy - .get(cesc("#\\/p")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => text.trim() === "(12,2)"), - ); - cy.get(cesc("#\\/p")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(12,2)"); - }); - cy.get(cesc("#\\/p2")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(12,5)"); - }); - cy.get(cesc("#\\/p3")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(12,0)"); - }); - }); - - it("update property of property", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (1,2) - (3,4) - - - - - - - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/P")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("(1,2)"); - }); - - cy.get(cesc("#\\/_updatevalue1_button")).click(); - cy.waitUntil(() => - cy - .get(cesc("#\\/P")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => text.trim() === "(2,2)"), - ); - - cy.get(cesc("#\\/_updatevalue2_button")).click(); - cy.waitUntil(() => - cy - .get(cesc("#\\/P")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => text.trim() === "(4,2)"), - ); - - cy.get(cesc("#\\/_updatevalue3_button")).click(); - cy.waitUntil(() => - cy - .get(cesc("#\\/P")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => text.trim() === "(3,7)"), - ); - - cy.get(cesc("#\\/_updatevalue1_button")).click(); - cy.waitUntil(() => - cy - .get(cesc("#\\/P")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => text.trim() === "(6,7)"), - ); - - cy.get(cesc("#\\/_updatevalue2_button")).click(); - cy.waitUntil(() => - cy - .get(cesc("#\\/P")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => text.trim() === "(12,7)"), - ); - }); - - it("chained updates", () => { - 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("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - - cy.get(cesc("#\\/quad")).should("not.exist"); - - cy.get(cesc("#\\/trip_button")).click(); - cy.get(cesc("#\\/x")).should("contain.text", "3x"); - cy.get(cesc("#\\/y")).should("contain.text", "4y"); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4y"); - }); - - cy.get(cesc("#\\/trip_button")).click(); - - cy.get(cesc("#\\/x")).should("contain.text", "9x"); - cy.get(cesc("#\\/y")).should("contain.text", "16y"); - - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("16y"); - }); - }); - - it("chained updates on multiple sources", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - x - y - z - - - - - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - cy.get(cesc("#\\/z")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - - cy.get(cesc("#\\/quad")).should("not.exist"); - - cy.get(cesc("#\\/trip_button")).click(); - cy.get(cesc("#\\/x")).should("contain.text", "3x"); - cy.get(cesc("#\\/y")).should("contain.text", "4y"); - - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - cy.get(cesc("#\\/z")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("z"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4y"); - }); - - cy.get(cesc("#\\/doub_button")).click(); - cy.get(cesc("#\\/z")).should("contain.text", "2z"); - cy.get(cesc("#\\/y")).should("contain.text", "16y"); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - cy.get(cesc("#\\/z")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2z"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("16y"); - }); - - cy.get(cesc("#\\/trip_button")).click(); - cy.get(cesc("#\\/x")).should("contain.text", "9x"); - cy.get(cesc("#\\/y")).should("contain.text", "64y"); - - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9x"); - }); - cy.get(cesc("#\\/z")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("2z"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("64y"); - }); - }); - - it("chained updates, copies don't copy triggers", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` -

n: 1

-

m1: 1

-

m2: 1

- -

-

-

-

$uv

- - - - `, - }, - "*", - ); - }); - - cy.get(cesc2("#/n")).should("have.text", "1"); - cy.get(cesc2("#/m1")).should("have.text", "1"); - cy.get(cesc2("#/m2")).should("have.text", "1"); - - cy.get(cesc2("#/uv")).click(); - cy.get(cesc2("#/n")).should("have.text", "2"); - cy.get(cesc2("#/m1")).should("have.text", "2"); - cy.get(cesc2("#/m2")).should("have.text", "1"); - - cy.get(cesc2("#/uv2")).click(); - cy.get(cesc2("#/n")).should("have.text", "3"); - cy.get(cesc2("#/m1")).should("have.text", "2"); - cy.get(cesc2("#/m2")).should("have.text", "2"); - - cy.get(cesc2("#/uv3")).click(); - cy.get(cesc2("#/n")).should("have.text", "4"); - cy.get(cesc2("#/m1")).should("have.text", "2"); - cy.get(cesc2("#/m2")).should("have.text", "2"); - - // Note: we expect the macro to trigger the updateValue with triggerWith="uv" - // because it doesn't have a name. - cy.get(cesc2("#/pmacro") + " button").click(); - cy.get(cesc2("#/n")).should("have.text", "5"); - cy.get(cesc2("#/m1")).should("have.text", "3"); - cy.get(cesc2("#/m2")).should("have.text", "2"); - }); - - it("update based on trigger", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (-1,2) - - x - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - - cy.get(cesc("#\\/trip")).should("not.exist"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -1, y: -7 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 3, y: -4 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 1, y: 7 }, - }); - cy.get(cesc("#\\/x")).should("contain.text", "3x"); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 5, y: 9 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -3, y: 4 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -6, y: 5 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 4, y: 2 }, - }); - cy.get(cesc("#\\/x")).should("contain.text", "9x"); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9x"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 9, y: 7 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9x"); - }); - }); - }); - - it("update triggered when click", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (-1,2) - - x - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - - cy.get(cesc("#\\/trip")).should("not.exist"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -1, y: -7 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "pointClicked", - componentName: "/P", - args: { name: "/P" }, - }); - cy.get(cesc("#\\/x")).should("contain.text", "3x"); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 5, y: 9 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "pointClicked", - componentName: "/P", - args: { name: "/P" }, - }); - cy.get(cesc("#\\/x")).should("contain.text", "9x"); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9x"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 9, y: 7 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9x"); - }); - }); - }); - - it("update triggered when object focused", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (-1,2) - - x - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - - cy.get(cesc("#\\/trip")).should("not.exist"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -1, y: -7 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "pointFocused", - componentName: "/P", - args: { name: "/P" }, - }); - cy.get(cesc("#\\/x")).should("contain.text", "3x"); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 5, y: 9 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "pointFocused", - componentName: "/P", - args: { name: "/P" }, - }); - cy.get(cesc("#\\/x")).should("contain.text", "9x"); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9x"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 9, y: 7 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9x"); - }); - }); - }); - - it("update triggered when objects clicked, trigger with unnamed copies", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (-1,2) - - - $P - - - $P{name="P2"} - - - - - - x - - - -

- `, - }, - "*", - ); - }); - cy.get(cesc2("#/_text1")).should("have.text", "a"); //wait for page to load - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - let PcopyName = - stateVariables["/_graph1"].activeChildren[0].componentName; - - cy.get(cesc2("#/x") + " .mjx-mrow") - .eq(0) - .should("have.text", "x"); - - cy.get(cesc("#\\/trip")).should("not.exist"); - - cy.log("clicking unnamed copy triggers update"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "pointClicked", - componentName: PcopyName, - args: { name: PcopyName }, - }); - }); - cy.get(cesc2("#/x")).should("contain.text", "3x"); - cy.get(cesc2("#/x") + " .mjx-mrow") - .eq(0) - .should("have.text", "3x"); - - cy.log("clicking copy with an assignNames does not trigger update"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "pointClicked", - componentName: "/P2", - args: { name: "/P2" }, - }); - }); - cy.get(cesc2("#/bi")).click(); - cy.get(cesc2("#/bi2")).should("have.text", "true"); // to make sure core responded - - cy.get(cesc2("#/x") + " .mjx-mrow") - .eq(0) - .should("have.text", "3x"); - - cy.log("clicking point with copySource does not trigger update"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "pointClicked", - componentName: "/_point2", - args: { name: "/_point2" }, - }); - }); - cy.get(cesc2("#/bi")).click(); - cy.get(cesc2("#/bi2")).should("have.text", "false"); // to make sure core responded - - cy.get(cesc2("#/x") + " .mjx-mrow") - .eq(0) - .should("have.text", "3x"); - - cy.log("clicking unnamed copy triggers update again"); - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "pointClicked", - componentName: PcopyName, - args: { name: PcopyName }, - }); - }); - cy.get(cesc2("#/x")).should("contain.text", "9x"); - cy.get(cesc2("#/x") + " .mjx-mrow") - .eq(0) - .should("have.text", "9x"); - }); - }); - - it("chained updates based on trigger", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (-1,2) - - x - y - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - - cy.get(cesc("#\\/trip")).should("not.exist"); - cy.get(cesc("#\\/quad")).should("not.exist"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -1, y: -7 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 3, y: -4 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 1, y: 7 }, - }); - cy.get(cesc("#\\/x")).should("contain.text", "3x"); - cy.get(cesc("#\\/y")).should("contain.text", "4y"); - - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 5, y: 9 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -3, y: 4 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -6, y: 5 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 4, y: 2 }, - }); - - cy.get(cesc("#\\/x")).should("contain.text", "9x"); - cy.get(cesc("#\\/y")).should("contain.text", "16y"); - - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("16y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 9, y: 7 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("16y"); - }); - }); - }); - - it("chained updates based on trigger on same object", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (-1,2) - - x - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - - cy.get(cesc("#\\/trip")).should("not.exist"); - cy.get(cesc("#\\/quad")).should("not.exist"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -1, y: -7 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 3, y: -4 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 1, y: 7 }, - }); - // since second change could be asynchronous, use other form so that cypress will wait - cy.get(cesc("#\\/x")).find(".mjx-mrow").should("have.text", "12x"); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("12x"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 5, y: 9 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("12x"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -3, y: 4 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("12x"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -6, y: 5 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("12x"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 4, y: 2 }, - }); - // since second change could be asynchronous, use other form so that cypress will wait - // (keep other form of test to make it clear we aren't actually changing anything) - cy.get(cesc("#\\/x")).find(".mjx-mrow").should("have.text", "144x"); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("144x"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 9, y: 7 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("144x"); - }); - }); - }); - - it("triggerWhen supercedes chaining", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (-1,2) - - x - y - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - - cy.get(cesc("#\\/trip")).should("not.exist"); - cy.get(cesc("#\\/quad")).should("not.exist"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -1, y: -7 }, - }); - cy.get(cesc("#\\/y")).should("contain.text", "4y"); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 3, y: -4 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 1, y: 7 }, - }); - cy.get(cesc("#\\/x")).should("contain.text", "3x"); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 5, y: 9 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -3, y: -4 }, - }); - cy.get(cesc("#\\/y")).should("contain.text", "16y"); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("16y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -6, y: -5 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("16y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 4, y: 2 }, - }); - cy.get(cesc("#\\/x")).should("contain.text", "9x"); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("16y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 9, y: 7 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("16y"); - }); - }); - }); - - it("triggerSet", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Boolean to swap:

-

Say hello:

-

Count: 1

- - - - - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", ""); - cy.get(cesc("#\\/n")).should("have.text", "1"); - - cy.get(cesc("#\\/_triggerset1_button")).click(); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "2"); - - cy.get(cesc("#\\/_triggerset1_button")).click(); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", " hello hello"); - cy.get(cesc("#\\/n")).should("have.text", "3"); - - cy.get(cesc("#\\/_triggerset1_button")).click(); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello hello hello"); - cy.get(cesc("#\\/n")).should("have.text", "4"); - }); - - it("triggerSet and chain to updatevalue", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Boolean to swap:

-

Say hello:

-

Count: 1

- - - - - - - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", ""); - cy.get(cesc("#\\/n")).should("have.text", "1"); - - cy.get(cesc("#\\/_triggerset1_button")).click(); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "2"); - - cy.get(cesc("#\\/_triggerset1_button")).click(); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", " hello hello"); - cy.get(cesc("#\\/n")).should("have.text", "3"); - - cy.get(cesc("#\\/_triggerset1_button")).click(); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello hello hello"); - cy.get(cesc("#\\/n")).should("have.text", "4"); - }); - - it("triggerSet and chain to triggerset", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

Boolean to swap:

-

Say hello:

-

Count: 1

-

Count down: 5

- - - - - - - - - - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", ""); - cy.get(cesc("#\\/n")).should("have.text", "1"); - cy.get(cesc("#\\/m")).should("have.text", "5"); - cy.get(cesc("#\\/_triggerset2")).should("not.exist"); - - cy.get(cesc("#\\/_triggerset1_button")).click(); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "2"); - cy.get(cesc("#\\/m")).should("have.text", "4"); - - cy.get(cesc("#\\/_triggerset1_button")).click(); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", " hello hello"); - cy.get(cesc("#\\/n")).should("have.text", "3"); - cy.get(cesc("#\\/m")).should("have.text", "3"); - - cy.get(cesc("#\\/_triggerset1_button")).click(); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello hello hello"); - cy.get(cesc("#\\/n")).should("have.text", "4"); - cy.get(cesc("#\\/m")).should("have.text", "2"); - }); - - it("triggerSet based on trigger", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (-1,2) - - x - y - - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - - cy.get(cesc("#\\/trip")).should("not.exist"); - cy.get(cesc("#\\/quad")).should("not.exist"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -1, y: -7 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 3, y: -4 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 1, y: 7 }, - }); - cy.get(cesc("#\\/x")).should("contain.text", "3x"); - cy.get(cesc("#\\/y")).should("contain.text", "4y"); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 5, y: 9 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -3, y: 4 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -6, y: 5 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("3x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("4y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 4, y: 2 }, - }); - cy.get(cesc("#\\/x")).should("contain.text", "9x"); - cy.get(cesc("#\\/y")).should("contain.text", "16y"); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("16y"); - }); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 9, y: 7 }, - }); - cy.get(cesc("#\\/x")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("9x"); - }); - cy.get(cesc("#\\/y")) - .find(".mjx-mrow") - .eq(0) - .invoke("text") - .then((text) => { - expect(text.trim()).equal("16y"); - }); - }); - }); - - it("triggerWhen supercedes chaining for triggerset", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (-1,2) - - -

Boolean to swap:

-

Say hello:

-

Count: 1

-

Count down: 5

- - - - - - - - - - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", ""); - cy.get(cesc("#\\/n")).should("have.text", "1"); - cy.get(cesc("#\\/m")).should("have.text", "5"); - cy.get(cesc("#\\/_triggerset1")).should("not.exist"); - cy.get(cesc("#\\/_triggerset2")).should("not.exist"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -1, y: -7 }, - }); - cy.get(cesc("#\\/n")).should("have.text", "2"); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", ""); - cy.get(cesc("#\\/m")).should("have.text", "4"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 3, y: -4 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", ""); - cy.get(cesc("#\\/n")).should("have.text", "2"); - cy.get(cesc("#\\/m")).should("have.text", "4"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 1, y: 7 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "2"); - cy.get(cesc("#\\/m")).should("have.text", "4"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 5, y: 9 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "2"); - cy.get(cesc("#\\/m")).should("have.text", "4"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -3, y: -4 }, - }); - cy.get(cesc("#\\/n")).should("have.text", "3"); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/m")).should("have.text", "3"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -6, y: -5 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "3"); - cy.get(cesc("#\\/m")).should("have.text", "3"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 4, y: 2 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", " hello hello"); - cy.get(cesc("#\\/n")).should("have.text", "3"); - cy.get(cesc("#\\/m")).should("have.text", "3"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 9, y: 7 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", " hello hello"); - cy.get(cesc("#\\/n")).should("have.text", "3"); - cy.get(cesc("#\\/m")).should("have.text", "3"); - }); - }); - - it("triggerset supercedes triggerWhen for updateValue children", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (-1,2) - - -

Boolean to swap:

-

Say hello:

-

Count: 1

- - - - - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", ""); - cy.get(cesc("#\\/n")).should("have.text", "1"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -1, y: -7 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", ""); - cy.get(cesc("#\\/n")).should("have.text", "1"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 3, y: -4 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", ""); - cy.get(cesc("#\\/n")).should("have.text", "1"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 1, y: 7 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "2"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 5, y: 9 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "2"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -3, y: -4 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "2"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -6, y: -5 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "2"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 4, y: 2 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", " hello hello"); - cy.get(cesc("#\\/n")).should("have.text", "3"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 9, y: 7 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", " hello hello"); - cy.get(cesc("#\\/n")).should("have.text", "3"); - }); - }); - - it("triggerset supercedes chaining for updateValue children", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - (-1,2) - - -

Boolean to swap:

-

Say hello:

-

Count: 1

-

Count down: 5

- - - - - - - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", ""); - cy.get(cesc("#\\/n")).should("have.text", "1"); - cy.get(cesc("#\\/m")).should("have.text", "5"); - cy.get(cesc("#\\/_triggerset1")).should("not.exist"); - cy.get(cesc("#\\/uv")).should("not.exist"); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -1, y: -7 }, - }); - cy.get(cesc("#\\/m")).should("have.text", "4"); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", ""); - cy.get(cesc("#\\/n")).should("have.text", "1"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 3, y: -4 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", ""); - cy.get(cesc("#\\/n")).should("have.text", "1"); - cy.get(cesc("#\\/m")).should("have.text", "4"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 1, y: 7 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "2"); - cy.get(cesc("#\\/m")).should("have.text", "4"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 5, y: 9 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "2"); - cy.get(cesc("#\\/m")).should("have.text", "4"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -3, y: -4 }, - }); - cy.get(cesc("#\\/m")).should("have.text", "3"); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "2"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: -6, y: -5 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "true"); - cy.get(cesc("#\\/hello")).should("have.text", " hello"); - cy.get(cesc("#\\/n")).should("have.text", "2"); - cy.get(cesc("#\\/m")).should("have.text", "3"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 4, y: 2 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", " hello hello"); - cy.get(cesc("#\\/n")).should("have.text", "3"); - cy.get(cesc("#\\/m")).should("have.text", "3"); - }); - - cy.window().then(async (win) => { - await win.callAction1({ - actionName: "movePoint", - componentName: "/P", - args: { x: 9, y: 7 }, - }); - cy.get(cesc("#\\/b")).should("have.text", "false"); - cy.get(cesc("#\\/hello")).should("have.text", " hello hello"); - cy.get(cesc("#\\/n")).should("have.text", "3"); - cy.get(cesc("#\\/m")).should("have.text", "3"); - }); - }); - - it("update value to blank string", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - something - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/t")).should("have.text", "something"); - cy.get(cesc("#\\/toBlank_button")).click(); - cy.get(cesc("#\\/t")).should("have.text", ""); - }); - - it("updatevalue warnings with invalid targets", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - 1 -

1

- - - - - - `, - }, - "*", - ); - }); - - cy.log("click the update value buttons"); - cy.get(cesc2("#/_updatevalue1")).click(); - cy.get(cesc2("#/_updatevalue2")).click(); - cy.get(cesc2("#/_updatevalue3")).click(); - - cy.log("make sure core has responded"); - cy.get(cesc2("#/bi")).click(); - cy.get(cesc2("#/b")).should("have.text", "true"); - - cy.window().then(async (win) => { - let errorWarnings = await win.returnErrorWarnings1(); - - expect(errorWarnings.errors.length).eq(0); - expect(errorWarnings.warnings.length).eq(3); - - expect(errorWarnings.warnings[0].message).contain( - 'Invalid target for : cannot find a state variable named "invalid" on a ', - ); - expect(errorWarnings.warnings[0].level).eq(1); - expect(errorWarnings.warnings[0].doenetMLrange.lineBegin).eq(5); - expect(errorWarnings.warnings[0].doenetMLrange.charBegin).eq(3); - expect(errorWarnings.warnings[0].doenetMLrange.lineEnd).eq(5); - expect(errorWarnings.warnings[0].doenetMLrange.charEnd).eq(49); - - expect(errorWarnings.warnings[1].message).contain( - 'Invalid target for : cannot find a state variable named "value" on a

', - ); - expect(errorWarnings.warnings[1].level).eq(1); - expect(errorWarnings.warnings[1].doenetMLrange.lineBegin).eq(6); - expect(errorWarnings.warnings[1].doenetMLrange.charBegin).eq(3); - expect(errorWarnings.warnings[1].doenetMLrange.lineEnd).eq(6); - expect(errorWarnings.warnings[1].doenetMLrange.charEnd).eq(41); - - expect(errorWarnings.warnings[2].message).contain( - "Invalid target for : cannot find target", - ); - expect(errorWarnings.warnings[2].level).eq(1); - expect(errorWarnings.warnings[2].doenetMLrange.lineBegin).eq(7); - expect(errorWarnings.warnings[2].doenetMLrange.charBegin).eq(3); - expect(errorWarnings.warnings[2].doenetMLrange.lineEnd).eq(7); - expect(errorWarnings.warnings[2].doenetMLrange.charEnd).eq(55); - }); - }); - // TODO: what is supposed to happen here? it.skip("update value set to ignore read only flag", () => { let doenetML = ` @@ -3240,532 +77,4 @@ describe("UpdateValue Tag Tests", function () { cy.get(cesc("#\\/m")).should("have.text", "2"); cy.get(cesc("#\\/n")).should("have.text", "30"); }); - - it("math in label", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/update")).should("contain.text", "we have ∏3i=1yi"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/update"].stateValues.label).eq( - "we have \\(\\prod_{i=1}^3 y_i\\)", - ); - }); - }); - - it("label is name", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a - - - `, - }, - "*", - ); - }); - cy.get(cesc("#\\/_text1")).should("have.text", "a"); //wait for page to load - - cy.get(cesc("#\\/SwapIt")).should("contain.text", "Swap It"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/SwapIt"].stateValues.label).eq("Swap It"); - }); - }); - - it("update essential label value", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/uv")).should("contain.text", "Button"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/uv"].stateValues.label).eq(""); - }); - - cy.get(cesc("#\\/uv")).click(); - - cy.get(cesc("#\\/uv")).should("contain.text", "Hello!"); - - cy.window().then(async (win) => { - let stateVariables = await win.returnAllStateVariables1(); - expect(stateVariables["/uv"].stateValues.label).eq("Hello!"); - }); - }); - - it("bug fix: no duplicate name error, #1921", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - - - - - - - `, - }, - "*", - ); - }); - - cy.get(cesc("#\\/_updatevalue1")).should("contain.text", "Move tail"); - cy.get(cesc("#\\/_triggerset1")).should("contain.text", "Move both"); - cy.get(cesc("#\\/vh") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,0)"); - cy.get(cesc("#\\/vt") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,0)"); - - cy.get(cesc("#\\/_updatevalue1")).click(); - - cy.get(cesc("#\\/vt") + " .mjx-mrow").should("contain.text", "(3,4)"); - - cy.get(cesc("#\\/vt") + " .mjx-mrow") - .eq(0) - .should("have.text", "(3,4)"); - cy.get(cesc("#\\/vh") + " .mjx-mrow") - .eq(0) - .should("have.text", "(4,4)"); - - cy.get(cesc("#\\/_triggerset1")).click(); - cy.get(cesc("#\\/vt") + " .mjx-mrow").should("contain.text", "(7,2)"); - - cy.get(cesc("#\\/vt") + " .mjx-mrow") - .eq(0) - .should("have.text", "(7,2)"); - cy.get(cesc("#\\/vh") + " .mjx-mrow") - .eq(0) - .should("have.text", "(9,4)"); - }); - - it("updatevalue in graph", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - a -

n: 1

- - - - - -

Anchor 1 coordinates: $updatevalue1.anchor

-

Anchor 2 coordinates: $updatevalue2.anchor

-

Change anchor 1 coordinates:

-

Change anchor 2 coordinates:

-

Position from anchor 1: $updatevalue1.positionFromAnchor

-

Position from anchor 2: $updatevalue2.positionFromAnchor

-

Change position from anchor 1 - - upperRight - upperLeft - lowerRight - lowerLeft - left - right - top - bottom - center - -

-

Change position from anchor 2 - - upperRight - upperLeft - lowerRight - lowerLeft - left - right - top - bottom - center - -

-

Draggable 1: $draggable1

-

Draggable 2: $draggable2

-

Change draggable 1

-

Change draggable 2

-

Disabled 1: $disabled1

-

Disabled 2: $disabled2

-

Change disabled 1

-

Change disabled 2

-

Fixed 1: $fixed1

-

Fixed 2: $fixed2

-

Change fixed 1

-

Change fixed 2

-

FixLocation 1: $fixLocation1

-

FixLocation 2: $fixLocation2

-

Change fixLocation 1

-

Change fixLocation 2

-

- - `, - }, - "*", - ); - }); - - // TODO: how to click on the buttons and test if they are disabled? - - cy.get(cesc("#\\/_text1")).should("have.text", "a"); // to wait until loaded - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,3)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(0,0)"); - - cy.get(cesc("#\\/pPositionFromAnchor1")).should( - "have.text", - "Position from anchor 1: upperright", - ); - cy.get(cesc("#\\/pPositionFromAnchor2")).should( - "have.text", - "Position from anchor 2: center", - ); - cy.get(cesc("#\\/positionFromAnchor1")).should("have.value", "1"); - cy.get(cesc("#\\/positionFromAnchor2")).should("have.value", "9"); - cy.get(cesc("#\\/pDraggable1")).should( - "have.text", - "Draggable 1: true", - ); - cy.get(cesc("#\\/pDraggable2")).should( - "have.text", - "Draggable 2: true", - ); - - cy.log("move updatevalues by dragging"); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveButton", - componentName: "/updatevalue1", - args: { x: -2, y: 3 }, - }); - win.callAction1({ - actionName: "moveButton", - componentName: "/updatevalue2", - args: { x: 4, y: -5 }, - }); - }); - - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow").should( - "contain.text", - "(4,−5)", - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−2,3)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(4,−5)"); - - cy.log("move updatevalues by entering coordinates"); - - cy.get(cesc("#\\/anchorCoords1") + " textarea").type( - "{home}{shift+end}{backspace}(6,7){enter}", - { force: true }, - ); - cy.get(cesc("#\\/anchorCoords2") + " textarea").type( - "{home}{shift+end}{backspace}(8,9){enter}", - { force: true }, - ); - - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow").should( - "contain.text", - "(8,9)", - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(6,7)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(8,9)"); - - cy.log("change position from anchor"); - cy.get(cesc("#\\/positionFromAnchor1")).select("lowerLeft"); - cy.get(cesc("#\\/positionFromAnchor2")).select("lowerRight"); - - cy.get(cesc("#\\/pPositionFromAnchor1")).should( - "have.text", - "Position from anchor 1: lowerleft", - ); - cy.get(cesc("#\\/pPositionFromAnchor2")).should( - "have.text", - "Position from anchor 2: lowerright", - ); - - cy.log("make not draggable"); - - cy.get(cesc("#\\/draggable1")).click(); - cy.get(cesc("#\\/draggable2")).click(); - cy.get(cesc("#\\/pDraggable1")).should( - "have.text", - "Draggable 1: false", - ); - cy.get(cesc("#\\/pDraggable2")).should( - "have.text", - "Draggable 2: false", - ); - - cy.log("cannot move updatevalues by dragging"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveButton", - componentName: "/updatevalue1", - args: { x: -10, y: -9 }, - }); - win.callAction1({ - actionName: "moveButton", - componentName: "/updatevalue2", - args: { x: -8, y: -7 }, - }); - }); - - // since nothing will change, wait for boolean input to change to know core has responded - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/b")).should("have.text", "true"); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(6,7)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(8,9)"); - - cy.log("make draggable again"); - - cy.get(cesc("#\\/draggable1")).click(); - cy.get(cesc("#\\/draggable2")).click(); - cy.get(cesc("#\\/pDraggable1")).should( - "have.text", - "Draggable 1: true", - ); - cy.get(cesc("#\\/pDraggable2")).should( - "have.text", - "Draggable 2: true", - ); - - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveButton", - componentName: "/updatevalue1", - args: { x: -10, y: -9 }, - }); - win.callAction1({ - actionName: "moveButton", - componentName: "/updatevalue2", - args: { x: -8, y: -7 }, - }); - }); - - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow").should( - "contain.text", - "(−8,−7)", - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−10,−9)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−8,−7)"); - - cy.log("fix location"); - - cy.get(cesc("#\\/fixLocation1")).click(); - cy.get(cesc("#\\/fixLocation2")).click(); - cy.get(cesc("#\\/pFixLocation1")).should( - "have.text", - "FixLocation 1: true", - ); - cy.get(cesc("#\\/pFixLocation2")).should( - "have.text", - "FixLocation 2: true", - ); - - cy.log("can change coordinates entering coordinates only for button 1"); - - cy.get(cesc("#\\/anchorCoords2") + " textarea").type( - "{home}{shift+end}{backspace}(3,4){enter}", - { force: true }, - ); - cy.get(cesc("#\\/anchorCoords1") + " textarea").type( - "{home}{shift+end}{backspace}(1,2){enter}", - { force: true }, - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow").should( - "contain.text", - "(1,2)", - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−8,−7)"); - - cy.log("cannot move updatevalues by dragging"); - cy.window().then(async (win) => { - win.callAction1({ - actionName: "moveButton", - componentName: "/updatevalue1", - args: { x: 4, y: 6 }, - }); - win.callAction1({ - actionName: "moveButton", - componentName: "/updatevalue2", - args: { x: 7, y: 8 }, - }); - }); - - // since nothing will change, wait for boolean input to change to know core has responded - cy.get(cesc("#\\/bi")).click(); - cy.get(cesc("#\\/b")).should("have.text", "false"); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(1,2)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−8,−7)"); - - cy.log("can change position from anchor only for button 1"); - cy.get(cesc("#\\/positionFromAnchor2")).select("bottom"); - cy.get(cesc("#\\/positionFromAnchor1")).select("top"); - - cy.get(cesc("#\\/pPositionFromAnchor1")).should( - "have.text", - "Position from anchor 1: top", - ); - cy.get(cesc("#\\/pPositionFromAnchor2")).should( - "have.text", - "Position from anchor 2: lowerright", - ); - - cy.log("can change disabled attribute"); - cy.get(cesc("#\\/disabled1")).click(); - cy.get(cesc("#\\/disabled2")).click(); - cy.get(cesc("#\\/pDisabled1")).should("have.text", "Disabled 1: false"); - cy.get(cesc("#\\/pDisabled2")).should("have.text", "Disabled 2: true"); - - cy.log("make completely fixed"); - cy.get(cesc("#\\/fixed1")).click(); - cy.get(cesc("#\\/fixed2")).click(); - cy.get(cesc("#\\/pFixed1")).should("have.text", "Fixed 1: true"); - cy.get(cesc("#\\/pFixed2")).should("have.text", "Fixed 2: true"); - - cy.log("can change coordinates entering coordinates only for button 1"); - - cy.get(cesc("#\\/anchorCoords2") + " textarea").type( - "{home}{shift+end}{backspace}(7,8){enter}", - { force: true }, - ); - cy.get(cesc("#\\/anchorCoords1") + " textarea").type( - "{home}{shift+end}{backspace}(5,6){enter}", - { force: true }, - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow").should( - "contain.text", - "(5,6)", - ); - - cy.get(cesc("#\\/pAnchor1") + " .mjx-mrow") - .eq(0) - .should("have.text", "(5,6)"); - cy.get(cesc("#\\/pAnchor2") + " .mjx-mrow") - .eq(0) - .should("have.text", "(−8,−7)"); - - cy.log("can change position from anchor only for button 1"); - cy.get(cesc("#\\/positionFromAnchor2")).select("left"); - cy.get(cesc("#\\/positionFromAnchor1")).select("right"); - - cy.get(cesc("#\\/pPositionFromAnchor1")).should( - "have.text", - "Position from anchor 1: right", - ); - cy.get(cesc("#\\/pPositionFromAnchor2")).should( - "have.text", - "Position from anchor 2: lowerright", - ); - - cy.log("can change disabled attribute only for button 1"); - cy.get(cesc("#\\/disabled2")).click(); - cy.get(cesc("#\\/disabled1")).click(); - cy.get(cesc("#\\/pDisabled1")).should("have.text", "Disabled 1: true"); - cy.get(cesc("#\\/pDisabled2")).should("have.text", "Disabled 2: true"); - }); - - it("handle removed updateValue when shadowing", () => { - cy.window().then(async (win) => { - win.postMessage( - { - doenetML: ` - - - - -

true

- - - - - - - -
-
- - `, - }, - "*", - ); - }); - - cy.get(".doenet-viewer p").eq(0).should("have.text", "true"); - - cy.get(".doenet-viewer button").click(); - cy.get(".doenet-viewer p").eq(0).should("have.text", "false"); - cy.get(".doenet-viewer button").should("not.exist"); - }); });